web-dev-qa-db-ja.com

0ミリ秒に設定されている場合、setTimeoutは何をしていますか?

JavaScriptでは、setTimeout(callback, delay)は「callbackミリ秒後にdelayを呼び出す」ことを意味します。しかし、delay0である場合はどうでしょうか? callbackをすぐに呼び出す必要がありますか?

次のコードを実行すると表示されるものが原因で混乱しています。

setTimeout(function() { 
    console.log('AAA');
}, 0); // Call this in 0 milliseconds 

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
for (i = 0; i < 1000; i++) {
    console.log('CCC'); 
}
for (i = 0; i < 1000; i++) {
    console.log('DDD'); 
}
for (i = 0; i < 1000; i++) {
    console.log('EEE'); 
}

これにより、以下がコンソールに記録されます。

console_log

AAAがそれよりずっと早く記録されるのを期待していました。すぐに呼び出されるべき関数の前に、console.logへの4000の呼び出しを実行する時間がありました。

遅延が0ミリ秒に設定されている場合、誰かがsetTimeoutが何をしているのか説明できますか?

39
DDan

いくつかの有用な事実は、何が起こっているのかを明確にするのに役立ちます。

  1. JavaScriptはシングルスレッドです。非同期コールバックは、メッセージキューに配置されたメッセージに割り当てられます。
  2. 現在実行中のコードがない場合、イベントループはメッセージキューをポーリングし、処理される(実行される)行の次のメッセージを要求します。
  3. setTimeoutは、指定された遅延が経過した後、このキューの最後に(提供されたコールバックを使用して)メッセージを追加します。

(注:これは、setTimeout呼び出しの遅延が確実なものではないことを意味します。コールバックが実行される前の最小遅延です。 。実際にかかる時間は、キュー内のそれより前のメッセージを処理するのにかかる時間によって異なります。

では、遅延が0に設定されているとどうなりますか?新しいメッセージはすぐにキューに追加され、現在実行中のコードが終了し、以前に追加されたメッセージが処理されると処理されます。

コードで何が起こっているのか

setTimeout…を呼び出すとき

setTimeout(function() { 
    console.log('AAA');
}, 0);

…指定されたコールバックでメッセージがキューに追加されます。コードの残りの部分…

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
// etc.

…同期実行を継続します。完全に終了すると、イベントループは次のメッセージを求めてメッセージキューをポーリングし、setTimeoutコールバックを持つものを見つけて処理します(コールバックが実行されます)。

コールバックは、どれだけ時間がかかっても、現在実行中のコードが終了した後afterのみ実行されます。

参考文献

イベントループの詳細については、以下を参照してください。

59
Jordan Gray