Node.jsドキュメントでの19の予期しない発見

Nodeをかなりよく知っていると思います。 過去3年間、私が取り組んできたサイトの1つでは、それなしではできませんでした。 しかし、私はまだドキュメントを適切に読んでいません。



インターフェイス、プロパティ、メソッド、関数、データ型、およびWeb開発に関連する他のすべてに関する有用なことを書き留めたいです。 だから私は知識のギャップを埋めます。 現在、Node.jsのドキュメントで忙しく、それ以前はHTML、DOM、Web API、CSS、SVG、およびEcmaScriptの資料に取り組んでいました。



画像






Node.jsのドキュメントを読むと、今まで知らなかった多くの素晴らしいことがわかりました。 この短い記事でそれらを共有したいと思います。 最も興味深いものから始めます。 新しい友人に私のガジェットを見せるとき、私は通常同じことをします。



1.ユニバーサルパーサーとしてのクエリ文字列モジュール



次のようなキー/値のペアの配列を生成するいくつかの風変わりなデータベースからデータを取得したとしましょう:



name:Sophie;shape:fox;condition:new



。 これがJavaScriptオブジェクトに簡単に変換できると信じるのは当然です。 したがって、空のオブジェクトを作成し、次に配列を作成して、文字列を「 ;



」で分割します;



「。 次に-この配列の各要素を循環し、「 :



」記号で行を再度分割します。 その結果、各行から取得された最初の要素は新しいオブジェクトのプロパティ名になり、2番目の要素は値になります。



すべてが正しいですか?



いいえ、正しくありません。 同様の状況では、 querystring



を使用するだけで十分です。



 const weirdoString = `name:Sophie;shape:fox;condition:new`; const result = querystring.parse(weirdoString, `;`, `:`); // : // { //   name: `Sophie`, //   shape: `fox`, //   condition: `new`, // };
      
      





2.デバッグ:V8インスペクター



--inspect



してNodeを実行すると、URLが報告されます。 Chromeでこのアドレスに移動します。 そして今-楽しい驚き。 Chrome開発者ツールを使用してNode.jsデバッグできます。 幸せな時代が来ました。 Paul Irishのこのトピックに関するガイドを次に示します。



この機能はまだ実験的なものですが、私は喜んで使用していますが、これまでのところ私は失敗していません。



3. nextTickとsetImmediateの違い



他の多くのソフトウェアメカニズムと同様に、これらの2つの関数の違いを覚えるのは、より意味のある名前を付けると非常に簡単です。



したがって、関数process.nextTick()



process.nextTick()



と呼ばれるべきです。 setImmediate()



sendThisToTheEndOfTheQueue()



です。



ちなみに、Node v0.10.0以降のnextTick



最適化に関する有用な資料があります。 少し余談。 Reactのprops



stuffThatShouldStayTheSameIfTheUserRefreshes



を呼び出し、 state



stuffThatShouldStayTheSameIfTheUserRefreshes



を呼び出すべきだといつも思っていstuffThatShouldBeForgottenIfTheUserRefreshes



。 これらの名前の長さが同じであるという事実は、偶然の一致と考えてください。



4. Server.listenはパラメーターを持つオブジェクトを受け入れます



私は、たとえば、「オプション」という名前のオブジェクトの形式でパラメーターを渡すことを支持しています。関数への入力で多くのパラメーターが予想される場合のアプローチではなく、さらに名前がなく、厳密に定義された順序で配置する必要があります 判明したように、サーバーが要求リッスンするように構成すると、パラメーターを持つオブジェクトを使用できます。



 require(`http`) .createServer() .listen({   port: 8080,   host: `localhost`, }) .on(`request`, (req, res) => {   res.end(`Hello World!`); });
      
      





この便利な機能はかなりよく隠れていました。 http.Server



ドキュメントで、それについての言葉ではありません。 ただし、これはnet.Server



の説明にnet.Server



、その継承者はhttp.Server



です。



5.相対ファイルパス



fs



モジュールに渡されるファイルシステムのパスは相対パスです。 参照ポイントは、 process.cwd()



によって返される現在の作業ディレクトリです。 おそらく、誰もがすでにこれを知っていますが、私は常にフルパスなしではできないと思っていました。



 const fs = require(`fs`); const path = require(`path`); //     ... fs.readFile(path.join(__dirname, `myFile.txt`), (err, data) => { //  -  }); //     ? fs.readFile(`./path/to/myFile.txt`, (err, data) => { //  -  });
      
      





6.ファイルパスの解析



通常、ファイルパスから名前と拡張子を取得する必要があるときは、正規表現を使用しました。 今、私はこれが絶対に必要ないことを理解しています。 同じことは標準の手段でできます。



 myFilePath = `/someDir/someFile.json`; path.parse(myFilePath).base === `someFile.json`; // true path.parse(myFilePath).name === `someFile`; // true path.parse(myFilePath).ext === `.json`; // true
      
      





7.コンソールでのログの色付け



console.dir(obj, {colors: true})



コンストラクトを使用すると、プロパティと値がコンソールで色付き強調表示されたオブジェクトを表示できることを知らなかったふりをします。 これにより、ログの読み取りが容易になります。



8.管理setInterval()



たとえば、 setInterval()



を使用して、データベースを1日に1回クリーニングします。 デフォルトでは、 setInterval()



を使用して実行されるようにスケジュールされたコードがあるまで、Nodeイベントループは停止しません。 Nodeに休憩を与えたい場合(これからどのような利点が得られるかわかりません)、 unref()



関数を使用します。



 const dailyCleanup = setInterval(() => { cleanup(); }, 1000 * 60 * 60 * 24); dailyCleanup.unref();
      
      





ただし、ここでは注意が必要です。 Nodeがビジーでなくなった場合(たとえば、接続を待機しているHTTPサーバーがない場合)、シャットダウンします。



9.プロセスのシグナル完了の定数



殺したいなら、おそらくすでにこれをしているでしょう:



 process.kill(process.pid, `SIGTERM`);
      
      





このデザインについて悪いことは何も言えません。 しかし、タイプミスによるミスがチームに侵入した場合はどうでしょうか? プログラミングの歴史において、そのようなケースは知られています。 ここの2番目のパラメーターは文字列または対応する整数である必要があるため、何か間違ったことを書いても驚くことではありません。 エラーを防ぐために、これを行うことができます:



 process.kill(process.pid, os.constants.signals.SIGTERM);
      
      





10. IPアドレスの確認



Node.jsには、 IPアドレスチェックするための組み込みツールがあります 。 これを行うために、正規表現を複数回記述していました。 より多くの心のために十分ではなかった。 正しい方法は次のとおりです。



 require(`net`).isIP(`10.0.0.1`)
      
      





4



を返します。



 require(`net`).isIP(`cats`)
      
      





0



を返し0







そうです、猫はIPアドレスではありません。



例では、文字列に一重引用符を使用していることに気づいたかもしれません。 私はこれを行うのが好きですが、奇妙に見えると思うので、私はこれを言及する必要があると考えますが、私自身は本当に理由を知りません。 一般的に、これは私のスタイルです。



11.行末文字、os.EOL



コードで行末文字を指定したことがありますか? え? すべて、光を消します。 ここでは、特にこれを行った人にとっては素晴らしいことです: os.EOL



。 Windowsでは、他のすべてのOSで\r\n



になります- \n



os.EOL



と、異なるオペレーティングシステム間で一貫したコード動作が可能になります。



執筆時点では、このトピックの内容が十分ではないため、ここで修正します。 この投稿の以前のバージョンの読者は、 os.EOL



を使用すると問題が発生する可能性があることを指摘しました。 事実、ここでは特定のファイルでCRLF( \r\n



)またはLF( \n



)のいずれかを使用できるという仮定から進む必要がありますが、そのような仮定を完全に確信することはできません。



オープンソースプロジェクトがあり、特定の改行オプションの使用を強制したい場合、 eslintルールがあります。 確かに、Gitがテキストで機能する場合は役に立ちません。



それでも、 os.EOL



は役に立たないおもちゃではありません。 たとえば、このことは、他のオペレーティングシステムに転送する予定のないログファイルを生成する場合に役立ちます。 この場合、 os.EOL



は、たとえばWindows Serverで使用されているメモ帳を表示するために、そのようなファイルの正しい表示を保証します。



 const fs = require(`fs`); //      CRLF fs.readFile(`./myFile.txt`, `utf8`, (err, data) => { data.split(`\r\n`).forEach(line => {   //  -  }); }); //       const os = require(`os`); fs.readFile(`./myFile.txt`, `utf8`, (err, data) => { data.split(os.EOL).forEach(line => {   //  -  }); });
      
      





12. HTTPステータスコード



ノードには、HTTPステータスコードとその名前を含む「参照」があります。 私はhttp.STATUS_CODES



オブジェクトについて話してhttp.STATUS_CODES



ます。 そのキーは状態コードであり、値はその名前です。









オブジェクトhttp.STATUS_CODES



使用方法は次のとおりです。



 someResponse.code === 301; // true require(`http`).STATUS_CODES[someResponse.code] === `Moved Permanently`; // true
      
      





13.サーバーの不要なシャットダウンの防止



以下のようなコードがサーバーのシャットダウンにつながることは、私にとっていつも少し奇妙に思えました。



 const jsonData = getDataFromSomeApi(); //   !  ! const data = JSON.parse(jsonData); //    .
      
      





このようなナンセンスを防ぐために、Node.jsのアプリケーションの先頭に、 未処理の例外をコンソールに表示するような構造を配置できます。



 process.on(`uncaughtException`, console.error);
      
      





もちろん、私は正しい考えにいるので、私はPM2を使用して、できる限りすべてをラップしますtry…catch



注文するようにプログラムするときにブロックをtry…catch



ますが、ホームプロジェクトでは...



このアプローチは決して「 開発のベストプラクティス 」の1つではなく、大規模で複雑なアプリケーションでの使用はおそらく悪い考えであるという事実に特に注意を喚起したいと思います。 誰かが書いたブログ投稿を信頼するか、公式のドキュメントを信頼するかを自分で決めてください。



14.一度だけの短い言葉()



on()



メソッドon()



加えて、 EventEmitter



オブジェクトEventEmitter



once()



メソッドもあります。 私はこのことを地球上で最後に知っている人であると確信しています。 したがって、私は誰もが理解できる単純な例にとどまります。



 server.once(`request`, (req, res) => res.end(`No more from me.`));
      
      





15.カスタマイズ可能なコンソール



コンソールは、以下の設計を使用して構成でき、独自の出力ストリームを渡します。



 new console.Console(standardOut, errorOut)
      
      





なんで? よく分かりません。 たぶん、データをファイル、ソケット、または他の場所に出力するコンソールを作成したいかもしれません。



16. DNSクエリ



NodeがDNSクエリの結果をキャッシュしていないことを口説いた 。 したがって、特定のURLに複数回アクセスすると、不要なクエリに貴重なミリ秒が費やされます。 この場合、 dns.lookup()



を使用して自分でDNSクエリを実行し、結果をキャッシュできます。 または、同じことを行うdnscacheパッケージを使用します。



 dns.lookup(`www.myApi.com`, 4, (err, address) => { cacheThisForLater(address); });
      
      





17. FSモジュール:地雷原



プログラミングスタイルが私のものに似ている場合、つまり、「ドキュメントを斜めに読み、動作するまでコードをいじります」というようなものであれば、 fs



問題から安全ではありません。 開発者はNodeとさまざまなオペレーティングシステムとの相互作用を統合することを目指して素晴らしい仕事をしましたが、その可能性は無限ではありません。 その結果、さまざまなオペレーティングシステムの機能は、採掘された鋭いサンゴ礁のようなコードの海の表面を破壊します。 このドラマでは、サンゴ礁の1つに乗ることができるボートの役割を果たします。



残念ながら、 fs



関連する違いは、通常の「Windowsと他のすべてのユーザー」に要約されていないため、「Windowsを使用するユーザー」という考えの裏にそれを振り切ることはできません。 (最初は、ここでWeb開発における反Windows感情についてのスピーチ全体を書きましたが、最終的にそれを削除することにしました。さもなければ、私の説教から私の額に目が行きました)。



ここで、一言で言えば、 fs



モジュールのドキュメントで見つけたものです。 これらの啓示は、揚げた鶏よりも悪くない人がいると思います。





(私はファッションに遅れをとっていない、私はAppleのOSを「macOS」と呼んでいるが、古い名前であるOS Xが別の世界に行ってから2か月経っていない。)



18.ネットモジュールはhttpモジュールの2倍の速度です



Node.jsのドキュメントを読んで、 net



モジュールが重要であることに気付きました。 これはhttp



モジュールの下にあります。 これにより、サーバーの相互作用を整理する必要がある場合(判明したため、必要な場合)、 net



モジュールのみを使用する価値があると思いました。



システムのネットワーキングに密接に関与している人は、そのような質問をする必要があるとはまったく信じないかもしれませんが、私は突然サーバーの世界に陥り、HTTPのみを知っているWeb開発者です。 これらすべてのTCP、ソケット、ストリームに関するすべてのこのおしゃべり...私にとっては、 日本のラップのようなものです。 つまり、私には理解できないように思えますが、興味をそそられるように聞こえます。



それを理解し、 net



http



で実験し、それらを比較するために、いくつかのサーバーをセットアップし(日本語のラップを聞いていることを願っています)、リクエストをロードしました。 その結果、 http.Server



は1秒あたり約3400のリクエストを処理でき、 http.Server



は約5500でした。さらに、 net.Server



簡単です。



興味があれば、私が実験したクライアントとサーバーのコード。 興味がない場合は、ページを長時間スクロールする必要があることをおizeびします。



これがclient.jsのコードです。



 //    .  –  TCP-,  –  HTTP (    server.js). //         . //       . const net = require(`net`); const http = require(`http`); function parseIncomingMessage(res) { return new Promise((resolve) => {   let data = ``;   res.on(`data`, (chunk) => {     data += chunk;   });   res.on(`end`, () => resolve(data)); }); } const testLimit = 5000; /*  ------------------  */ /*  --  NET client  --  */ /*  ------------------  */ function testNetClient() { const netTest = {   startTime: process.hrtime(),   responseCount: 0,   testCount: 0,   payloadData: {     type: `millipede`,     feet: 100,     test: 0,   }, }; function handleSocketConnect() {   netTest.payloadData.test++;   netTest.payloadData.feet++;   const payload = JSON.stringify(netTest.payloadData);   this.end(payload, `utf8`); } function handleSocketData() {   netTest.responseCount++;   if (netTest.responseCount === testLimit) {     const hrDiff = process.hrtime(netTest.startTime);     const elapsedTime = hrDiff[0] * 1e3 + hrDiff[1] / 1e6;     const requestsPerSecond = (testLimit / (elapsedTime / 1000)).toLocaleString();     console.info(`net.Server handled an average of ${requestsPerSecond} requests per second.`);   } } while (netTest.testCount < testLimit) {   netTest.testCount++;   const socket = net.connect(8888, handleSocketConnect);   socket.on(`data`, handleSocketData); } } /*  -------------------  */ /*  --  HTTP client  --  */ /*  -------------------  */ function testHttpClient() { const httpTest = {   startTime: process.hrtime(),   responseCount: 0,   testCount: 0, }; const payloadData = {   type: `centipede`,   feet: 100,   test: 0, }; const options = {   hostname: `localhost`,   port: 8080,   method: `POST`,   headers: {     'Content-Type': `application/x-www-form-urlencoded`,   }, }; function handleResponse(res) {   parseIncomingMessage(res).then(() => {     httpTest.responseCount++;     if (httpTest.responseCount === testLimit) {       const hrDiff = process.hrtime(httpTest.startTime);       const elapsedTime = hrDiff[0] * 1e3 + hrDiff[1] / 1e6;       const requestsPerSecond = (testLimit / (elapsedTime / 1000)).toLocaleString();       console.info(`http.Server handled an average of ${requestsPerSecond} requests per second.`);     }   }); } while (httpTest.testCount < testLimit) {   httpTest.testCount++;   payloadData.test = httpTest.testCount;   payloadData.feet++;   const payload = JSON.stringify(payloadData);   options[`Content-Length`] = Buffer.byteLength(payload);   const req = http.request(options, handleResponse);   req.end(payload); } } /*  --  Start tests  --  */ // flip these occasionally to ensure there's no bias based on order setTimeout(() => { console.info(`Starting testNetClient()`); testNetClient(); }, 50); setTimeout(() => { console.info(`Starting testHttpClient()`); testHttpClient(); }, 2000);
      
      





これがserver.jsです。



 //    .  – TCP,  – HTTP. //          JSON,      ,       . const net = require(`net`); const http = require(`http`); function renderAnimalString(jsonString) { const data = JSON.parse(jsonString); return `${data.test}: your are a ${data.type} and you have ${data.feet} feet.`; } /*  ------------------  */ /*  --  NET server  --  */ /*  ------------------  */ net .createServer((socket) => {   socket.on(`data`, (jsonString) => {     socket.end(renderAnimalString(jsonString));   }); }) .listen(8888); /*  -------------------  */ /*  --  HTTP server  --  */ /*  -------------------  */ function parseIncomingMessage(res) { return new Promise((resolve) => {   let data = ``;   res.on(`data`, (chunk) => {     data += chunk;   });   res.on(`end`, () => resolve(data)); }); } http .createServer() .listen(8080) .on(`request`, (req, res) => {   parseIncomingMessage(req).then((jsonString) => {     res.end(renderAnimalString(jsonString));   }); });
      
      





19. REPLモードのトリック



  1. REPLモードで作業する場合、つまり、ターミナルnode



    書き込んでEnterを押すと、 .load someFile.js



    ようなコマンドを入力でき、システムは要求されたファイルをロードします(たとえば、そのようなファイルに一連の定数を設定できます)。



  2. このモードでは、環境変数NODE_REPL_HISTORY=""



    を設定して、ファイルへの履歴の書き込みを無効にすることができます。 さらに、過去に移動できるREPL履歴ファイルが~/.node_repl_history



    保存されていることがわかりました(少なくとも覚えています)。



  3. アンダースコア文字「



    は、最後に実行された式の結果を格納する変数の名前です。 役に立つと思う。



  4. NodeがREPLモードで起動すると、モジュールは自動的に(より正確には、要求に応じて)ロードされます。 たとえば、コマンドラインでos.arch()



    と入力するだけで、OSのアーキテクチャを確認できます。 require(`os`).arch();



    ような構造 必要ありません。



まとめ



ご覧のとおり、ドキュメントを読むことは良いことです。 その地域でさえ、たくさんの新しいものを見つけることができます。 私の発見がお役に立てば幸いです。



ところで、Node.jsについて他に興味深いことはありますか? もしそうなら-共有:)



All Articles