29

私がそうするとしましょう

setTimeout(foo, 0);

...

setTimeout(bar, 0);

foo が bar の前に実行を開始することを確認できますか? バーに 0 の代わりに 1、10、または 100 のタイムアウトを使用するとどうなりますか?

簡単な実験によると、タイムアウト値が等しい場合、タイムアウト ターゲットは setTimeouts 自体と同じ順序で実行されますが、この動作に依存しても安全ですか?

4

5 に答える 5

17

この動作に依存するのは安全ではありません。私は、すべて setTimeout(..., 0) を使用して、多数の関数をスケジュールするテスト スクリプトを作成しました (そして、これらの関数も多数の関数をスケジュールします)。関数が呼び出される順序は、常に同じではありませんでしたsetTimeout が呼び出された順序(少なくとも、スクリプトを実行するために使用した Chrome 11 では)。

ここでスクリプトを表示/実行できます: http://jsfiddle.net/se9Jn/ (スクリプトはブラウザー間の互換性のために YUI を使用しますが、Y.later は内部で setTimeout を使用します)。

スクリプトを実行してコンソールをじっと見ているだけでは、おそらく問題のある順序は表示されないことに注意してください。ただし、スクリプトを開始し、別のタブに切り替え、いくつかのページをロードして、テスト ページに戻ると、コンソールにコールバックの順序が正しくないというエラーが表示されます。

保証された順序が必要な場合は、前の関数の最後に次の関数をスケジュールすることをお勧めします。

setTimeout(foo, 0);

...

function foo() {

    ...

    setTimeout(bar, 0);
}
于 2011-05-13T22:19:07.283 に答える
15

私は Firefox のソース コードを読みましたが、少なくともそのブラウザーでは、減少しない順序で指定されたタイムアウトの連続性が保証されています。そうでなければ、すべての賭けは無効になります。

具体的には、特定の実行コンテキストで n のタイムアウトを設定し、次に m のタイムアウトを設定すると (n <= m)、ターゲットはタイムアウトが設定された順序で実行されます。

しかし、私の言葉を鵜呑みにしないでください。ウィンドウの実装は nsGlobalWindow.cpp にあり、タイムアウトが実行キューのどこに行くかを実際に決定するメソッドはInsertTimeoutIntoListと呼ばれます。メソッドは、指定されたタイムアウト以下の最初のタイムアウトを探してキューを逆方向にトラバースし、その後に指定されたタイムアウトを挿入するように見えます。

もちろん、タイムアウトが設定されると、現在の時刻がタイムアウト値に追加されます。これが、ターゲットを順番に実行するために、タイムアウト値が減少しない順序でなければならない理由です。

于 2009-11-21T20:31:49.117 に答える
4

要するに、それを頼りにしないでください。これを見てください。

この図には消化すべき多くの情報がありますが、完全に理解することで、非同期 JavaScript 実行がどのように機能するかをよりよく理解できるようになります。

于 2009-11-21T18:12:46.840 に答える
2

遅延が実際に発生する可能性がある特定の最小値があり、それはOS、ブラウザー、ブラウザーのアクティビティー、およびコンピューターの負荷に大きく依存します。20ms未満でも違いはないと思うので、20msを下回らない傾向があります。

等しい2つの遅延を設定する場合、必ずしもその順序で発生することを意味するわけではありません。

あなたがそれが次のようなことをする傾向があるために行われることを確実にしたいのなら:

setTimeout(function() { 
  foo();
  setTimeout(bar, 20)
}, 20);

これは常に注文を保証します。

Firefoxを使用している場合、JavaScriptが実際にマルチスレッド化されていることを確認するには、IEではなく新しいブラウザーでサポートされているWebWorkerを確認することをお勧めします。

于 2009-11-21T18:22:50.313 に答える