1

http://jsfiddle.net/Codemonkey/ye5qv/2/

私は、setIntervalを使用して繰り返し発生する大きなワークロードを作成して、ブラウザーが作業の各反復の間に息を呑むことができるようにすることを試みています。上記の例では、フィボナッチ計算の各間隔の間に100ミリ秒の休憩をブラウザに与えていますが、ブラウザはfib()呼び出された瞬間からコールバックが呼び出された瞬間までまだフリーズしています。注:私の例では、ドキュメントが読み込まれてから1秒前にfibo関数が呼び出されないため、数秒間フリーズすることがはっきりとわかります。

正確に、このメソッドが機能しないのはなぜですか。また、どうすれば機能させることができますか?あるいは、同じ目標結果を達成できる他の方法はどれですか?繰り返しになりますが、setIntervalを使用して作業を分割する目的は、プロセス中にブラウザーがフリーズしたり、散らかったりしないようにすることです。

私はクロームを使用していて、主にV8エンジンに関心がありますが、xブラウザー互換のソリューションはボーナスです

4

3 に答える 3

4

残念ながら、JavaScriptsetIntervalsetTimeoutは完全に非同期ではないため、すべてが 1 つのスレッドで動作します。つまり、setIntervalコールバックが呼び出されると、メイン スレッドで実行され、他のすべての実行がブロックされます。

これについて詳しく説明している John Resig による素晴らしい投稿は次のとおりです: How JavaScript Timers Work

本当に非同期の JavaScript が必要な場合は、Web Workersなどを使用する必要があります。


他の人がここで指摘しているように、あなたの特定のケースでは、実際にはこの行に無限ループがあります:

for(var i = start; i < i+workload; i++)

あなたのコードを引き起こしているもの:

setTimeout(function() {
    processor(start + workload);
}, 100);

決して呼び出されないように。詳細については、 Guffa の優れた回答を参照してください。

ただし、私の答えの残りの部分はまだ適用されます.単純な操作以上のものを.gif同時にアニメーション化しようとしている場合は、Web Workers などを使用しなくてもフリーズまたはスタッターが発生する可能性があります。

于 2012-06-08T12:34:44.107 に答える
4

setTimeout問題は、コードが、制御をブラウザーに戻すために呼び出すポイントに到達しないことです。

これを変える:

for(var i = start; i < i+workload; i++)

に:

for(var i = start; i < start+workload; i++)

workload正の数であるためi < i + workload、false になることはないため、無限ループが発生します。


ブラウザーに制御を戻すときに 100 ミリ秒待つ必要はありません。ブラウザーにsetTimoutイベントを処理させるには呼び出しだけで十分なので、時間 0 を使用できます。

setTimeout(function() {
  processor(start + workload);
}, 0);

デモ: http://jsfiddle.net/Guffa/ye5qv/3/

于 2012-06-08T12:40:03.570 に答える
1

setIntervalこの行では、実際には呼び出されないことに気付きました

for(var i = start; i < i+workload; i++)

iは常に よりも小さいため、条件は常に真i+workloadであり、サイクルから抜け出すことはありません。ループ内の関数から戻るのは良いことです。

于 2012-06-08T12:39:42.680 に答える