2009-11-21 19 views
23

は私がJavascriptで等しいタイムアウトが順番に実行されていますか?

setTimeout(foo, 0); 

... 

setTimeout(bar, 0); 

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

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

+0

を使用すると、実行順序を気にしている場合

は、あなたがこれを行うことができます代わりにsetTimeout(callback, 0)の、保証の実行順序が必要な場合このページを参照してください。http://www.onsip.com/blog/2012/06/29/avoiding-javascript-settimeout-and-setinterval-problems –

答えて

4

要するに、カウントしないでください。 thisをご覧ください。

情報の多くは、消化するために、この 図にありますが、それを理解すること 完全にあなたの JavaScriptの実行がどのように動作するか、非同期のより良い 実現を与えるだろう。

+7

この記事では何も表示されませんこれは厳密に言います。問題は、ターゲット関数がいつ実行されるかということではなく、実行される順序です。 – jkl

+1

厳密な注文にはカウントしないでください。これは前述の記事の「非同期」のポイントです。 – jldupont

+4

確かに、実際の遅延は予想よりも長くなる可能性があり、インターバルはタイマーとは異なって動作しますが、記事で直接問題に対処していません。 'foo'を実行するのに0ミリ秒か100年かかるかにかかわらず、いつも' bar'の前に起こりますか?または、ブラウザが任意に選択できますか?私はこの上に標準(または少なくともいくつかの情報)がなければならないように感じる。 – Calvin

1

遅れが実際に起こる可能性があり、OS、ブラウザ、ブラウザのアクティビティ、およびコンピュータの負荷に大きく依存します。私はそれ以下のものは何の差もないと思うので、20ms以下にならない傾向があります。

2つの遅延を同じにすると、必ずしもその順序で起こるとは限りません。

あなたはそれが順番に行われることを確実にしたい場合は、私はこのような何かをする傾向がある:

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

これは常に順序を保証します。

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

+2

等しいタイムアウトが順不同で実行される特定の例を知っていますか? – jkl

+0

私はそれを保証する何も見たことがないので、それが重要なときには、それに応じて信頼しません。 –

+1

"最短"有益な遅延は実装とコンピュータの速度に依存しますが、現在の呼び出しスタックがクリアされるまで呼び出しを延期するため、 "0"はsetTimeoutに使用するのに便利な時間です。 – Nosredna

13

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

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

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

もちろん、タイムアウトが設定されると、現在の時計時刻がタイムアウト値に追加されます。これは、ターゲットが順番に実行されるためにタイムアウト値が非減少順になっている必要があるためです。

13

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

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

スクリプトを実行してコンソールを凝視しただけでは、問題の発注は見られないことに注意してください。しかし、スクリプトを起動して別のタブに切り替えていくつかのページを読み込んでテストページに戻ったら、コンソールに順不同のコールバックに関するエラーが表示されるはずです。

あなたは順序は保証が必要な場合は、私は前の関数の末尾に次の関数をスケジュール推薦:

setTimeout(foo, 0); 

... 

function foo() { 

    ... 

    setTimeout(bar, 0); 
} 
3

答えは:いいえ、実行順序は保証されません。私は時折、クロム40で非FIFO注文を見たことがあります。特に、タイムアウトが保留されている間にデバッガで一時停止すると、私も野生の珍しい目撃をしました - それは私が調査した事件の唯一のもっともらしい説明でした。

var queue = []; 
function handleQueue() { 
    queue.shift()(); 
} 
function queueCallback(callback) { 
    queue.push(callback); 
    setTimeout(handleQueue, 0); 
} 

さて、保証fooために、次のことができbar順:

queueCallback(foo); 
... 
queueCallback(bar); 
関連する問題