延遲執行功能(例如在自定義事件處理中)是JavaScript中的常見模式(請參閱here)。它曾經是使用setTimeout(myFunc,0)
是唯一的方法來做到這一點,但承諾現在有一個替代方案:Promise.resolve().then(myFunc)
。使用promises或setTimeout決定延遲函數的調用順序是什麼?
我假設這些幾乎都做同樣的事情,但是在包含自定義事件的庫上工作時,我想我會發現是否有差異,因此我將以下塊放入節點中:
var logfn=function(v){return function(){console.log(v)}};
setTimeout(logfn(1),0);
Promise.resolve().then(logfn(2));
logfn(3)();
我期待看到控制檯3,1,2,而是我看到了3,2,1。所以換句話說,承諾不等同於使用setTimeout和散發出來的塊的第一個。至少在Node中。
我在Chrome和Firefox中重複了測試,結果相同,但在Edge中出現爲3,1,2。我還希望非本機諾言庫在引擎蓋下使用setTimeout,這樣會出來與Edge相同。
什麼決定了這些調用順序的解決?這些不同的環境使用什麼模型來確定執行順序?以上任何情況是否代表標準或非標準行爲?
PS我沒有建議依靠任何這種保持一致,我只是好奇。
下面給出的答案後,我指出了正確的方向,並且在下面的評論中提到簡單地說,我發現了一個很好的article by Jake Archibald完整的答案(幾乎等同於我上面的代碼的例子),我儘管我會加在這裏,而不是將它埋在評論中。
FWIW,沒有什麼是* *保證異步執行任何特定的順序。你永遠不應該試圖首先依靠執行順序。這使得這個問題成爲關於實現細節的有趣討論,但實際上並沒有實際意義。 – deceze
也許,但我傾向於發現,我的編碼提高得越多,我越理解它是如何掛在一起的,即使是間接的。在仔細研究下面的答案之後,我也發現了幾乎完全是我上面的例子以及完整的解釋[這裏](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)。考慮到所有這些,我可以肯定的看到,推動微任務或macrotask隊列的具體情況可能是適當的,儘管需要確保只有macrotasks可用時沒有任何事情被破壞 –