ホームページ >ウェブフロントエンド >jsチュートリアル >Node.jsのイベントループの詳細説明

Node.jsのイベントループの詳細説明

php中世界最好的语言
php中世界最好的语言オリジナル
2018-03-16 15:35:051941ブラウズ

今回はNode.jsのイベントループの詳しい説明と、Node.jsのイベントループを使用する際の注意点についてお届けします。以下は実際のケースですので見てみましょう。

Node.jsもシングルスレッドのイベントループですが、その動作メカニズムはブラウザ環境とは異なります。

下の模式図を見てください

Node.jsのイベントループの詳細説明

上図によると、Node.jsの動作仕組みは以下の通りです。

(1) V8 エンジンは

JavaScript スクリプトを解析します。

(2) 解析されたコードは Node API を呼び出します。

(3) libuv ライブラリはノード API の実行を担当します。異なるタスクを異なるスレッドに割り当ててイベントループ(イベントループ)を形成し、タスクの実行結果を非同期でV8エンジンに返します。

(4) V8 エンジンは結果をユーザーに返します。

2 つのメソッド setTimeout と setInterval に加えて、Node.js は「Task

Queue」に関連する他の 2 つのメソッド、process.nextTick と setImmediate も提供します。これらは、「タスクキュー」についての理解を深めるのに役立ちます。

process.nextTick メソッドは、現在の「実行スタック」の終わり、つまり次のイベント ループ (メインスレッドが「タスク キュー」を読み取る) の前に、

コールバック関数 をトリガーできます。つまり、指定したタスクは常にすべての非同期タスクの前に発生します。 setImmediate メソッドは、現在の「タスク キュー」の末尾にイベントを追加します。つまり、指定したタスクは常に次のイベント ループで実行されます。これは setTimeout(fn, 0) とよく似ています。以下の例を参照してください (StackOverflow経由)。

process.nextTick(function A() {
  console.log(1);
  process.nextTick(function B(){console.log(2);});});setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');}, 0)// 1// 2// TIMEOUT FIRED

上記のコードでは、process.nextTick メソッドで指定されたコールバック関数は常に現在の「実行スタック」の最後でトリガーされるため、setTimeout で指定されたコールバック関数のタイムアウト前に関数 A が実行されるだけでなく、関数B もタイムアウトが発生する前に実行されます。これは、複数の process.nextTick ステートメントがある場合 (ネストされているかどうかに関係なく)、それらはすべて現在の「実行スタック」で実行されることを意味します。

次に、setImmediate を見てください。

setImmediate(function A() {
  console.log(1);
  setImmediate(function B(){console.log(2);});});setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');}, 0);

上記のコードでは、setImmediate と setTimeout(fn,0) のそれぞれに、次のイベント ループでトリガーされるコールバック関数 A とタイムアウトが追加されます。それでは、どのコールバック関数が最初に実行されるのでしょうか?答えは定かではありません。実行結果は、1--TIMEOUT FIRED--2 または TIMEOUT FIRED--1--2 となる場合があります。

混乱を招くのは、Node.js のドキュメントには、setImmediate で指定されたコールバック関数は常に setTimeout よりも前にランク付けされると記載されていることです。実際、これは再帰的に呼び出した場合にのみ発生します。

setImmediate(function (){
  setImmediate(function A() {
    console.log(1);
    setImmediate(function B(){console.log(2);});
  });
  setTimeout(function timeout() {
    console.log('TIMEOUT FIRED');
  }, 0);});// 1// TIMEOUT FIRED// 2

上記のコードでは、setImmediate と setTimeout は setImmediate にカプセル化されており、その実行結果は常に 1--TIMEOUT FIRED--2 になります。このとき、関数 A はタイムアウト前にトリガーされる必要があります。 TIMEOUT FIRED の 2 番目の順位 (つまり、関数 B がタイムアウト後にトリガーされる) については、setImmediate が常にイベントを次のイベント ループのラウンドに登録するため、関数 A と timeout は同じループのラウンドで実行されます。関数 B はループの次のラウンドで実行されます。

ここから、process.nextTick と setImmediate の重要な違いがわかります。複数の process.nextTick ステートメントは常に現在の「実行スタック」で一度に実行されますが、複数の setImmediate では複数のループの実行が必要になる場合があります。実際、これが Node.js バージョン 10.0 で setImmediate メソッドを追加した理由です。そうしないと、次のような process.nextTick への再帰呼び出しが無限に行われ、メイン スレッドが「イベント キュー」をまったく読み取れなくなります。

process.nextTick(function foo() {
  process.nextTick(foo);});

実際、ここで再帰的 process.nextTick を記述すると、Node.js は警告をスローし、それを setImmediate に変更するように求めます。

また、process.nextTickで指定したコールバック関数はこの「イベントループ」でトリガーされるのに対し、setImmediateで指定したコールバック関数は次の「イベントループ」でトリガーされるので、前者の方が必ず先に発生することがわかります。後者は実行効率も高い(「タスクキュー」を確認する必要がないため)。

この記事の事例を読んだ後は、この方法を習得したと思います。さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。

推奨読書:

JavaScriptのタイマーの詳細な説明

JavaScriptの実行メカニズムのイベントとコールバック関数の詳細な説明

ブラウザのマルチスレッドメカニズムの詳細な説明

js小さな問題

以上がNode.jsのイベントループの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。