JavaScript ステートメント (Chrome のコンソール内) が 1 ミリ秒で変数を何回while
インクリメントできるか疑問に思ったので、すぐにこのスニペットをコンソールに直接書きました:
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
問題は、それが永久に実行されることです。
なぜこれが起こっているのですか、どうすれば解決できますか?
JavaScript ステートメント (Chrome のコンソール内) が 1 ミリ秒で変数を何回while
インクリメントできるか疑問に思ったので、すぐにこのスニペットをコンソールに直接書きました:
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
問題は、それが永久に実行されることです。
なぜこれが起こっているのですか、どうすれば解決できますか?
これは、JavaScript 1の 1スレッドの性質に戻ります。何が起こるかは、ほとんどこれです:
run = false
ます。これは、現在の関数が実行された後に実行されるようにスケジュールされています (または現在アクティブになっているものは何でも)。setTimeout()
コールバックが実行されrun=false
ます。ご覧のとおり、setTimeout()
アプローチはここでは機能しません。条件の時間を確認することで回避できwhile
ますが、実際の測定値が改ざんされます。
1少なくともより実用的な目的では、シングルスレッドと見なすことができます。実際には、いわゆる「イベントループ」があります。そのループでは、すべての関数が実行されるまでキューに入れられます。新しい関数をキューに入れると、そのキュー内のそれぞれの位置に配置されます。現在の関数が終了した後setTimeout()
、エンジンはキューから次の関数を取得し (たとえば、導入されたタイミングに関して)、それを実行します。
その結果、すべての時点で関数が 1 つだけ実行されるため、実行がきれいになります。イベントには例外がいくつかありますが、これについては以下のリンクで説明しています。
参考のため:
https://stackoverflow.com/a/16757582/1169798
ここで、同様のシナリオがより詳細に説明されました
https://stackoverflow.com/a/2734311/1169798
JS がシングルスレッドと見なされる場合とそうでない場合の詳細な説明。
JavaScript はシングル スレッドであるため、ループ中は他に何も実行されません。
速度を計算するために常に時間を取得しなくても Chrome の真の速度を維持するには、次の JS コードを試すことができます。
var start = new Date().getTime()
var i = 0
while(i<1000000)
{
i++
}
var end = new Date().getTime()
var delta = end-start
var speed = i/delta
console.log(speed + " loops per millisecond")
Javascript はシングルスレッドです。つまり、一度に 1 つの命令のみを順番に実行します。
イベント システムは、他の多くの言語やライブラリと同様に、イベント ループによって処理されます。イベント ループは基本的にループであり、反復ごとにキュー内のメッセージをチェックし、イベントをディスパッチします。
JavaScript では (このパターンを実装する言語の mot のように)、イベント ループはスタックが空になると呼び出されます。
「実際の」プログラムは、舞台裏で次のようになります。
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
while(true) {
/*
* check for new messages in the queue and dispatch
* events if there are some
*/
processEvents();
}
そのため、タイムアウトが終了したという時計からのメッセージは処理されません。
イベントループの詳細: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop
もちろん、もう少し複雑です。ここで例を確認してください。( tl;dr:一部のブラウザー エンジンでは、一部の外部イベントはイベント ループに依存せず、発生するとすぐに起動され、現在のタスクがプリエンプトされます。しかし、キューにメッセージを追加するだけの setTimeout の場合はそうではありませんすぐに発火することはありません。)
While ループは setTimeout にアクセスしません。run true を設定するコードがあり、その後 false になることはありません。
JavaScript にはシングル スレッドがあり、どこでもシングル スレッドです。
この質問は良いと思います: JavaScript はシングルスレッドであることが保証されていますか?
コードがループしている場合、他の ocde は実行およびブロックされません。