1. ホーム
  2. javascript

なぜsetTimeoutは私のループをキャンセルしないのですか?

2023-12-01 11:36:37

質問

私は、JavaScriptの while ステートメントが1ミリ秒間に何回変数をインクリメントできるのか気になったので、このスニペットをコンソールに直接書き込んでみました。

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

問題は、永遠に実行されることです。

なぜこのようなことが起こるのでしょうか、また、どのように解決すればよいのでしょうか。

どのように解決するのですか?

これは、JavaScript のワンスレッドという性質に帰着します。 1 . 何が起こるかというと、ほとんどこれです。

  1. 変数が代入されます。
  2. 関数をスケジュールし run = false . これが実行されるようにスケジュールされます の後に実行されるようスケジュールされています(あるいは、現在アクティブなものは何でも)。
  3. エンドレスループを持ち、現在の関数の内部にとどまります。
  4. エンドレスループの後 ( 決して ) の後に setTimeout() コールバックが実行され run=false .

ご覧のように setTimeout() のアプローチではうまくいきません。この問題を回避するために while 条件で時間をチェックすることで回避できるかもしれませんが、これは実際の計測を改ざんすることになります。

1 少なくとも、より実用的な目的のために、シングルスレッドとして見ることができます。実際には、いわゆるイベントループと呼ばれるものが存在します。このループでは、すべての関数が実行されるまでキューに入れられます。新しい関数をキューに入れると、その関数はキュー内のそれぞれの位置に置かれます。 が終了した後、エンジンはキューから次の関数を取り出します。 setTimeout() で紹介されているようなタイミングを考慮して)次の関数をキューから取り出し、それを実行します。

その結果、どの時点でも1つの関数だけが実行され、実行はかなりシングルスレッド化されます。イベントには例外があり、以下のリンクで説明されています。


参考までに