[英]Are Node.js asynchronous tasks handled synchronously?
考慮以下代碼:
var some_expensive_task = function(i) {
setTimeout(function() {
var a = 1;
while (a < 100000000) {
Math.sqrt(a);
++a;
}
console.log('finished set' + i);
}, 0);
};
for (var i = 0; i < 70; ++i) {
console.log('start ' + i);
some_expensive_task(i);
console.log('end ' + i);
}
該程序的目的是使用setTimeout迭代並啟動70個CPU密集型異步任務。
正如所料,該計划的產出是:
start 1
end 1
...
start 69
end 69
finished set1
...
finished set69
在整個執行過程中,只有兩個過程。 我假設其中一個是空閑事件循環,另一個是100%運行的工作進程。
我是否正確理解當事件循環同步執行時,啟動的異步任務(無論來源如何)都按照調用它們的順序同步執行?
UPDATE
我仍然覺得我沒有把我的問題清楚地表達出來。 使用setTimeout是我能想到的准確安排一堆異步函數運行的唯一方法。 我想真正的問題是,如果我用setTimeout啟動三個異步函數,仍然是零延遲,是第二個我開始保證在第一個完成后運行,第三個保證在第二個完成后啟動嗎?
你在問題中使用了不正確的術語, Are Node.js asynchronous tasks handled synchronously
沒有多大意義。 測試用例不是你想象的那樣。 首先明確一些術語:
保證同步函數按其調用順序運行/完成。
異步函數可以在調用時進行並完成無序操作。
阻止操作是指一旦啟動就必須完成的操作,以便執行進一步發展。 除非在單獨的worker上運行,否則CPU密集型操作將被阻止。 循環本質上是阻塞的。 一旦它們啟動,它們將在執行下一個函數之前完成所有迭代。
setTimeout在當前時間之后至少調用傳遞函數至少x ms。 調用它意味着一旦x ms通過它就會在事件循環中對傳遞的函數進行排隊。 這只是延遲執行。
因此,考慮到上述事實,這就是為什么您的測試具有誤導性的原因:
首先,您的測試用例(您的CPU密集型函數)不是異步的,您將它包裝在異步的setTimeout周圍。 超時0僅表示它們將按照調用它們的順序執行。 所有回調函數都是同步的。
其次,日志中的開始和結束表示調用setTimeout的位置。 這將按預期順序進行。 超時0時,完成也將按順序完成。 是的,如果你保持超時等於他們,他們將按照通過的順序執行。 然后,這是許多可能的情況之一,其中結果類似於同步(如果超時按遞增順序怎么辦?)。 你問的問題可能適用於這些情況,但並非總是如此。
第三,如果你想模擬異步性(足以看到控制台上的無序行為),可以放松while循環並使用隨機超時( Math.random()*1000
)。 你會看到它們以任意方式完成。 這將是異步執行(setTimeout而不是回調)。
Node.js是單線程的,並且在一個進程中運行,因為JavaScript是單線程的。 因此你是對的。
是。 Javascript,包括NodeJS,是單線程的(除了少數例外)。
當您使用setTimeout(fn, 0)
,它會將當前調用堆棧清除后運行的函數排隊。 在您的示例中,這意味着for
循環將在“昂貴的任務”運行之前完成。
您的JS代碼在Node.js中的單個線程中運行。 所有其他本機Node.js API都是用C / C ++編寫的,可以是異步的,也可以在單獨的線程上運行。 有關更詳細的說明,請參閱此答案 。
我是否正確理解當事件循環同步執行時,啟動的異步任務(無論來源如何)都按照調用它們的順序同步執行?
是的,你是對的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.