blog

イベントループ

イベントループとは何ですか?実際のオブジェクトではなく、異なるフェーズの変換を表す概念です。生まれて、老いて、死んで、ループを形成するというライフサイクルに似ています。ある段階から次の段階にジャンプす...

Oct 8, 2020 · 4 min. read
シェア

イベントループとは何ですか?実際に存在する物体ではなく、さまざまな段階の変化を表す概念です。生まれて、老いて、死んで、リングを形成するというライフサイクルに似ています。ある段階から次の段階にジャンプするプロセスです。

. nodejsブラウザのイベントループは

nodejsでは、イベントループはステージングされます: 興味のある3つの主なフェーズは次のとおりです: タイマーポールチェック。

各ステージはそれ自身のタスクキューを持っています。

タイマーはsetTimeoutとsetIntervalを保持しています。

ポーリング・ステージは、例えば1秒後にタイマーでf1が実行された場合、ポーリング・ステージでは、その後にタスクがなければ、時間が来るまでポーリングで停止し続け、タイマーに移動してコールバックを実行します。

チェック段階でsetImmediateを保存

もう一つ質問ですが、イベントループとJSコードの実行はどちらが先に始まるのでしょうか?ほとんどの場合、すべての準備が整ったら、JSコードが実行を開始し、eventloopはpollステージにとどまって待機するはずです。しかし、eventloopがタイマステージに入る前に、JSの実行開始を待って、非常にゆっくりと開くこともあり得ます。そのため、setTimeoutとsetImmediateの順序に問題が生じます。

setTimeout(() => { console.log('setTimeout'); //f1 }, 0); setImmediate(() => { console.log('setImmediate'); //f2 });

nodeで実行すると、f1とf2のどちらが先に出力されますか?どちらかであることがわかりました。通常はf2が最初に表示され、次にf1が表示されるはずですが、実行するとf1が最初に表示され、次にf2が表示されることがあります。

timersステージにはタスクがないので、pollステージにジャンプして待機します。この時点で、JSコードが実行され、setTimeoutに遭遇してf1をtimerに入れ、setImmediateに遭遇してf2をcheckに入れます。で、f1が実行されます。

特殊なケース:eventloopがゆっくり開き、JSコードが先に実行されます。setTimeoutに遭遇したとき、f1をtimerに入れ、setImmediateに遭遇したとき、f2をcheckに入れました。このとき、eventloopがオープンされ、timerに入り、f1がすぐに実行されることがわかったので、そのまま実行しました。次にpollにジャンプして、実行されるタスクのcheckを見て、待たずにf2の実行のcheckに行きます。

つまり、setImmediateにあるものが必ず最初に実行されるというわけではありません。

f2を先に実行させるには?setTimeoutを使ってそれらをラップし、実行時間を全体として押し戻し、イベントループの開始準備ができたら、f1,f2を入れるようにします。

setTimeout(()=>{ setTimeout(() => { console.log('setTimeout'); //f1 }, 0); setImmediate(() => { console.log('setImmediate'); //f2 }); },1000)

eventloopはpollの段階で準備をして待機している必要があり、check中のタスクを見つけると、まずf2を実行し、それからタイマに戻ってf1を実行します。そのため、setImmediateは通常setTimeoutの前に実行されます。両者は異なるフェーズにあるからです。

process.nextTick()という非同期APIもありますが、どのような順序ですか? process.nextTick()は特別な非同期APIで、Event Loopのどのフェーズにも属しません。実際、NodeがこのAPIに遭遇すると、Event Loopは全く続行されず、process.nextTick()を実行するために直ちに停止し、この実行後にEvent Loopを継続します。

setTimeout(()=>{ setTimeout(() => { console.log('setTimeout'); //f1 }, 0); setImmediate(() => { console.log('setImmediate'); //f2 }); process.nextTick(() => { console.log('nextTick 1'); //f3 }); },1000)

JSコードの実行では、setTimeoutに遭遇するとf1をタイマーに入れ、setImmediateに遭遇するとf2をチェックに入れます。nextTickに遭遇すると、カレントステージで実行されますが、まだポーリングステージなので、まずf3を実行し、次にチェックステージに入ってf2を実行し、タイマーに戻ってf1を実行します。

nextTickは常にpollステージで実行されるわけではなく、どのステージにいても実行されます。

setTimeout(()=>{ setTimeout(() => { console.log('setTimeout'); //f1 process.nextTick(() => { console.log('nextTick 2'); //f4 }); }, 0); setImmediate(() => { console.log('setImmediate'); //f2 }); process.nextTick(() => { console.log('nextTick 1'); //f3 }); },1000)

f4は常にf1の後に続き、タイマーのステージで実行されます。簡単に言うと、nextTickは現在のステージの終了時に実行される次のステージにジャンプします。これは時間の中間転送ポイントにあります。

. ブラウザのイベントループ

ブラウザでは、イベントループはマクロタスクとマイクロタスクの2つのフェーズしかありません。

これはsetTimeout,Promise,async,awaitの順番に関係しています。

Read next

必須:Pythonのメモリ管理メカニズム

Pythonはインタプリタ言語、コンパイル言語、対話型言語、オブジェクト指向スクリプト言語の高レベルな組み合わせとして、多くのプログラミング言語とは異なり、Pythonの変数は事前に宣言する必要はありません、変数は型を指定する必要はありません、プログラマはメモリ管理を気にする必要はありません、Pythonインタプリタは自動回復を与えます。開発者はメモリ管理のメカニズムについてあまり気にする必要はありません。

Oct 8, 2020 · 7 min read