2011-05-21 15 views
2

これを理解するのを助けてください。Javascriptの非同期性の背後にあるもの - イベント駆動型システム

あなたはいくつかのメソッドを呼び出す関数を持っている:実行がメソッドまでに行かないことをコールバックや、私が実際に使用してしまった無名関数を持たない言語から、

function() { 
    methodA(function(){...}); 
    methodB(); 
    methodC(); 
} 

戻る。

コールバックでmethodAを呼び出すと、メソッドは非同期ではないメソッドを返すまで実行する必要があります。

たとえば、コールバックをオブジェクトに格納して、メソッドAを返すようにします。メソッドBとメソッドCが実行されます。ユーザーがボタンをクリックすると、ハンドラによってコールバックが実行されます。

私は、JavaやPython(マルチスレッドに関係しない)と比較して、javascriptに関して非同期的なものは何もないことを知りました.... Javaではコールバックはクロージャ/匿名メソッドではなく、 ...方法を「実行」し、それはまったく同じになり、少しだけより複雑もちろん、これはDOM

答えて

5

JavaScriptでコールバックはしないでください暗黙的に非同期動作を追加します。コールバック関数が呼び出されると、が正常に実行され、通常の関数と同様にが実行されます。このため

(実際には、コールバック関数が...ただ通常の関数である)、これは一例では、コールバックの実行が他の方法(に関係して実行されるときを決定することは不可能ですただし、methodAが呼び出される前に実行することはできません)。methodAまたはmethodBから呼び出すことも、後でクリックすることも、まったく呼び出さないこともできます。 (ただし、例外がない限り - または機能の一つは、他の機能のいずれかを呼び出す - そしてmethodAは、順番にmethodC前に実行されますmethodB前に実行されます。methodAが例外を投げたならば、methodBmethodCどちらが呼び出されます)。

が非同期動作を追加んように、ボタンのクリックなどのタイマーイベントやUIのアクションとして、非同期イベントソースです。

ただし、Javascriptにはスレッドが含まれていないか、サポートされていないことに注意してください。新しい非同期イベントがトリガーされる前に、Javascriptは「停止」する必要があります(実行は非同期イベントソースから呼び出されたコールバック関数から戻る必要があります)。 (非同期イベントは、[適切なものとして]キューに入れられますので、別のコールバックが実行に時間がかかりすぎると、タイマーイベントは "失われません")。while (true) {}は、ボタンイベントハンドラが処理されています。

ハッピーコーディング。


例の例(jsfiddle demo):

function invokeNow(callback) { 
    // nothing asynchronous going on here. 
    // the callback is invoked right now and the result is returned. 
    return callback() 
} 
alert(invokeNow(function() { return "Hello world!" })) 

function doLater(callback) { 
    // setup an asynchronous event 
    setTimeout(callback, 1000) 
    return "It isn't 'later' yet!" 
} 

alert(doLater(function() { 
    alert("Later!") 
    // note that this is running in the callback from the previous 
    // timer event. if this code was below the outer alert then 
    // it wouldn't have allowed the first timer callback to have occurred 
    // until the blocking while was complete 
    alert(doLater(function() { alert("I still ran!") })) 
    var end = (+new Date) + 4000 
    while ((+new Date) < end) { /* wait */ } 
    alert("I am done waiting") 
})) 

警告:Firefoxの4(4.0.1)と、上記のコードに問題があるようです。実証済みのように機能しますが、タイムアウトが約800msを下回る場合、予想される順序は実際の順序とは異なります。 SO: Asynchronous timer event running synchronously (“buggy”) in Firefox 4?を掲載していますので、うまくいけば解決策があります。予想通りの挙動は、Firefox 3、IE 9、とChrome 11

+0

偉大な説明pst、ありがとう – lisak

1
function main() { 
    methodA(function callback(){...}); 
    methodB(); 
    methodC(); 
} 

は、コールバックがすぐに実行されていないと仮定するとの具体的なイベントシステムをJSがあります。

実行順序:

  • methodA
  • methodB
  • methodC
  • ...スタックまで他のものが空である
  • コールバック
+2

を呼び出すときにコールバックが呼び出されます

function methodA(fn){ ... fn(); } 

。 methodAは、渡された関数をすぐに呼び出すことができます。 –

+0

スタックには何が含まれていますか教えてください。関数スコープ内のスタックだけを意味しますか?関数が戻るか終了するときにコールバックが呼び出されるようにするには?または、関数が返ってもコールバックを実行できますか? – lisak

+0

@Edgarスタックにはmainよりも後に実行されるものがすべて含まれています。 – Raynos

0

JavaScriptで働くあなたはsetIntervalsetTimeout、またはコールバックまたはonloadを使用してサーバに要求を行うを使用している場合を除き、シーケンシャルです。他のケースがあるかどうかはわかりません。あなたが何かを持っている場合は

:あなたはこれは真実ではありませんmethodA(function(){...})

関連する問題