2017-08-17 27 views
3

私は問題を回避するために努力してきましたが、成功していないため、私はあなたの助けを求めています。非同期コードの実行の説明

のは、たとえば次のよう考えてみましょう:

const async = require('async') 
var counter = 0 

var test = cb => { 
    if (++counter < 3) { 
    setTimeout(() => { 
     async.each([0,1,2], (item, callback) => { 
     console.log(item) 
     console.log('counter inner ' + counter) 
     test(cb) 
     callback() 
     },() => { 
      cb() 
     }) 
    }) 
    } else { 
     console.log('counter ' + counter) 
    } 
} 

var prom = new Promise((res, rej) => test(() => res('done'))) 
prom.then(res => console.log(res)) 

出力は次のようになります。私は理解していない何

0 
counter inner 1 
1 
counter inner 2 
counter 3 
2 
counter inner 3 
counter 4 
done 
0 
counter inner 4 
counter 5 
1 
counter inner 5 
counter 6 
2 
counter inner 6 
counter 7 

はそれが正しい二0counter inner 4を印刷した方法です。印刷しないでくださいcounter inner 1?そして約束は一度だけ解決されていますか? 2番目の解決呼び出しはどうなりますか?ありがとうございました。

+0

[なぜ私の変数は関数内で変更した後に変更されないのですか? - 非同期コードリファレンス](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Liam

+0

* [1つ単語の回答:非同期性](https://stackoverflow.com/a/23667087/542251)* – Liam

答えて

0

段階的に説明するのは難しいですが、私は後ろ向きに試してみましょう。あなたの出力から、あなたのコードのどの行が出力されたのかを言及しようとします。

// obviously starting inside the callback async runs for each of your 3 items 

    0 // console.log(item); 
    counter inner 1 // console.log('counter inner ' + counter); 

    1 // console.log(item); 
    counter inner 2 // console.log('counter inner ' + counter); 
    counter 3 // let's not forget you also call callback() for each item 
      // which evaluates this condition if (++counter < 3) and starting from here, 
      // it will be true and will run your else statement 
      // console.log('counter ' + counter); 

    2 // console.log(item); 
    counter inner 3 // console.log('counter inner ' + counter); 
    counter 4 // console.log('counter ' + counter); 

// at this point your promise is already resolved (and yes, only once) 
    done // prom.then(res => console.log(res)) 

// Now you are probably questioning where the following output comes from 
// remember this condition? if (++counter < 3) 
// before starting to evaluate to false and printing to console, once it 
// evaluated to true so setTimeout was called with your async callback 
// which scheduled it to run on the next "tick"*, which is right after the 
// promised was resolved 

    0 
    counter inner 4 
    counter 5 
    1 
    counter inner 5 
    counter 6 
    2 
    counter inner 6 
    counter 7 

これは、タイムアウト0のsetTimeout()の効果です。これはCのスレッド/プロセスの歩留まりと似ていますが、「すぐに実行する」と言われるようですが、実際には新しいJavaScriptコードを実行キューの最後に再キューします。

setTimeout文書によると、その2番目のパラメータは以下の通りです:指定された機能やコードが実行される前に

時間、ミリ秒(1000分の1秒)で、タイマーが 待たなければならないが。この パラメータを省略すると、値0が使用されます。つまり、できるだけ早く、「すぐに」またはより正確に を実行します。どちらの場合も、 では、実際の遅延が意図したよりも長くなることがあります。

ここでは、reasons for delays longer than specifiedについて詳しく読むことができます。

ifの条件をif(++counter < 2)に変更すると、今説明した内容を簡単に確認できます。それは本当に評価されないので、コンソール出力は"done"で停止することがわかります。

関連する問題