第3章. 非同期とイベント
この作品はAIを使って翻訳されている。ご意見、ご感想をお待ちしている:translation-feedback@oreilly.com
Nodeの最も重要な概念は、 イベント駆動モデルであり、 ノンブロッキングモデルとしても知られていることを学んだ。Nodeは非同期演算子をイベントと関連付け、内部で他の演算子から独立して実行する。非同期演算子が実行されると、Nodeはその演算子に依存するコードの実行をスケジュールする。
この章では、イベントとそのハンドラ関数であるコールバック、プロミス、リスナーの重要な概念について説明する。Nodeがイベントループとイベントキューで非同期操作のスケジューリングを管理する方法を学び、カスタムイベントエミッタとリスナー関数の作成と使用方法の例を見る。
同期と非同期の処理
ウェブ・ブラウザはシングル・スレッド環境で、ユーザ関連のコードはすべて1つのメイン・スレッドで実行される。Webサイトに遅い関数があると、その関数が実行されている間はユーザはスクロールすらできなくなる。それは、スクロールが単一のビジー・スレッドを使用する必要があるからだ。
Nodeのコード用に単一スレッド( )も用意されている。Nodeは内部的に他のスレッドと連動し、必要なときに手動でスレッドを作成することもできるが、メインスレッドをブロックするようなことをしないことが非常に重要だ。第1章でその簡単な抽象化の例を見た。メインスレッドをブロックすると、ウェブサーバ全体がリクエストに応答できなくなる、という例を見てみよう。
Nodeのウェブサーバに低速な同期演算子がある場合、HTTPリクエストの着信は貴重な単一スレッドをブロックし、最初の着信リクエストの下で低速演算子が動作している間は、ウェブサーバ全体が他の着信リクエストを処理できなくなる。
これを実際に見るために、第1章の単純なウェブサーバの例で、 for のループを使って低速演算をシミュレートしてみよう。メインスレッドをブロックする効果を示すために、サーバへの最初のリクエストに対してのみスロー演算を実行し、それ以降のリクエストはすべてスキップすることにしよう。これは単純なカウンタ変数でできる:
importhttpfrom'node:http';constslowOperation=()=>{for(leti=0;i<1e9;i++){// Simulate a synchronous delay}};letcounter=0;constserver=http.createServer((req,res)=>{counter=counter+1;if(counter===1){slowOperation();res.end('Slow Response');}else{res.end('Normal Response');}});server.listen(3000,()=>{console.log('Server is running...');});
最初のリクエスト(counter が1 のとき)は、完了するために低速演算を待たなければならないことに注意。他のリクエストは低速演算子を必要とせず、高速であるべきである。しかし、低速演算子は同期なので、最初のリクエストは低速になる だけでなく、それ以降のすべてのリクエストも最初のリクエストを待たなけれ ばならない! ...