2017-08-17 102 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 

我不明白的是它是如何在第二0後立即打印counter inner 4。不應該打印counter inner 1?一個承諾只能解決一次?第二次解決呼叫會發生什麼?謝謝。

+0

可能的重複[爲什麼我的變量在函數內部修改後沒有改變? - 異步代碼引用](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Liam

+0

* [One單詞答案:異步性。](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 

這是setTimeout()的超時時間爲0的效果。它就像C中的線程/進程產量。雖然它似乎說「立即運行」,但它實際上會在執行隊列末尾重新排隊新的javaScript代碼。

根據setTimeout文檔,它的第二個參數是以下各項:

的時間,以毫秒爲單位(千分之一秒),定時器應該 指定功能之前等待或執行的代碼。如果省略參數 ,則使用值0,意味着立即執行 或更準確地儘快執行。請注意,在任一情況下,實際延遲可能比預期的要長;

在這裏你可以閱讀更多關於reasons for delays longer than specified

您可以通過將if條件更改爲if(++counter < 2)來輕鬆驗證我剛剛解釋的內容。由於它永遠不會評估爲真,您將看到控制檯輸出停止在"done"