2011-12-23 18 views
4

JavaScriptはシングルスレッドであることを理解していますが、JavaScriptでの非同期イベント処理の理解を確認したいと思います。さらに重要なことは、潜在的な競争条件にさらされていないことを確認することです。JavaScriptイベント処理の競合条件?

は概念的には、当社のモバイルアプリは、このように動作します:モバイル・ページがロードされたときに我々は機能fooを呼び出す

  1. fooの終わり

  2. カウンタが0より大きい場合、我々は、(1秒の遅延で)再びfooを呼び出すためsetTimeoutを使用します。カウンタが0にヒットした場合は、新しいページを読み込みます。タイムアウトは変数に保存されます。

  3. ボタンをタップすると、関数do_tapが呼び出され、手順2で保存されたタイムアウト変数がクリアされます(その他のことも行います)。

do_tapfoo同じページ要素を更新し、我々は、彼らがお互いにステップしないことを確認したいの両方。

質問:

  1. タップはfooの実行中に発生したと仮定します。ブラウザdo_tapfooの終了後に実行を開始しますか?つまり、fooが起動すると、foodo_tapがインターリーブされることはありません。

  2. タップが最初に発生する場合はどうなりますか? do_tapは、fooが開始する前に完了することが保証されています。

+0

実行がシングルスレッドであるため、 'Do_tap'が返される前に' foo'が実行を開始することは不可能です(その逆もあります)。この記事を読んで、ブラウザの実行キューの仕組みを理解できます:http://ejohn.org/blog/how-javascript-timers-work/ –

答えて

6

Webワーカーと協調するフレームまたはウィンドウ(ここでは使用されていない)を除き、Javascriptは特定のウィンドウ内でシングルスレッド化されているため、そのウィンドウ内で同時に2つの実行スレッドが実行されることはありません。したがって、スレッドを使用する際の典型的な心配である可能性のある競合状態を心配する必要はありません。

Javascriptには、イベントキューがあります。あなたの現在の実行スレッドが完了するまで実行され、完了すると、JavaScriptのインタプリタはイベントキューをチェックして、何かすべきことがあるかどうかを調べます。そうであれば、そのイベントを起動し、別の実行スレッドを起動します。ほとんどすべてがそのイベントキュー(タイマー、キーイベント、サイズ変更イベント、マウスイベントなど)を通過します。

この件については、my other answersの関連資料を参照してください。

+1

これはフレームに別々の実行コンテキストがあることを除けば、ほとんどの場合真ですが、それらがすべてtop.myVariableのような同じデータにアクセスしている場合、競合条件を持つ可能性があります。 http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/を参照して、そのページ内のレースを検索してください。 –

+0

@JuanMendes - 良い点。私は私の答えを更新します。 – jfriend00

4

イベントの処理は、イベントが処理されるまでシングルスレッド化されます。その時間まで、他のイベントループは開始されません。

つまり、あるイベントに対してハンドラが実行されている間は、他のイベントのハンドラがそれを中断しません。

したがって、質問1と質問2の両方に対する回答は「はい」です。 (これはもちろん、ブラウザのバグはありませんが、これを考慮に入れれば、遠くになることはありません。これは、元に戻すための同期プリミティブのようなものではありません。その間にSafariは別の "DOMready"イベントハンドラを実行している間に "DOMready"イベントを発生させることができますが、明らかにバグでした)。

+0

ありがとうございました。 do_tap()とfoo()は両方とも同じページ要素を更新し、互いに踏み込めないことを確認したかったのです。断言してくれてありがとう。 – Crashalot

0

Do_tap() Do_tap()の実行中にfooが実行されることはありません。しかし、非同期プロセスがfoo()のようなデータベース要求で開始された場合、foo()は要求を終了し、DoTap()のデータベースにアクセスする可能性があり、foo()がDo_tap()が実行された後に理論的に呼び出されます。

0

私はこれを言っている人は誰もキャッチしませんでしたが、#2の答えは、異なるブラウザの実装が、キューに入れられたイベントが最初に処理される方法が微妙に違うことです。いいえ、インターリーブの可能性はありませんが、setTimeout(func、0)またはマウスイベントが最初に処理されるかどうかは、言語仕様によって保証されず、実際には重要です。 setTimeout(func、100)ですが、現在処理中のイベント中に受信した保留中のイベントより遅く処理されることが保証されています。

と言ってください。