您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關web中Promise.resolve().then(callback)比setTimeout(callback,0)更快的原因是什么的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
一、實驗
讓我們嘗試一個實驗。什么執行得更快:立即解決的承諾或立即超時(也就是0毫秒超時)?
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
// logs 'Resolved!'
// logs 'Timed out!'
Promise.resolve(1)是一個靜態函數,它返回一個立即解決的承諾。setTimeout(callback, 0)以0毫秒的延遲執行回調。
打開演示并檢查控制臺。您會注意到'Resolved!'首先記錄的是 ,然后是'Timeout completed!'。立即解決的承諾比立即超時處理得更快。
承諾過程可能會更快,因為Promise.resolve(true).then(...)在setTimeout(..., 0)? 夠公平的問題。
我們稍微改變一下實驗的條件,setTimeout(..., 0)先調用:
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
// logs 'Resolved!'
// logs 'Timed out!'
打開演示并查看控制臺。嗯……結果一樣!
setTimeout(..., 0)之前被調用Promise.resolve(true).then(...)。但是,'Resolved!'仍然記錄在'Timed out!'.
實驗表明,在立即超時之前處理立即解決的承諾。最大的問題是……為什么?
2.事件循環
與異步 JavaScript 相關的問題可以通過調查事件循環來回答。讓我們回顧一下異步 JavaScript 工作原理的主要組成部分。
注意:如果您不熟悉事件循環,我建議您在進一步閱讀之前先觀看此視頻。
調用堆棧是一個 LIFO(后進先出)結構,用于存儲代碼執行期間創建的執行上下文。簡單來說,調用堆棧執行函數。
Web API是異步操作(獲取請求、承諾、計時器)及其回調等待完成的地方。
任務隊列(也稱為宏任務)是一個 FIFO(先進先出)結構,它保存準備執行的異步操作的回調。例如,超時的回調setTimeout()——準備執行——被排入任務隊列。
作業隊列(也稱為微任務)是一個 FIFO(先進先出)結構,用于保存準備執行的承諾回調。例如,已履行的承諾的解決或拒絕回調在作業隊列中排隊。
最后,事件循環會永久監控調用堆棧是否為空。如果調用堆棧為空,則事件循環會查看作業隊列或任務隊列,并將任何準備執行的回調出列到調用堆棧中。
3. 作業隊列 vs 任務隊列
我們再從事件循環的角度來看這個實驗。我會一步一步分析代碼執行。
A) 調用棧執行setTimeout(..., 0)并調度一個定時器。timeout()回調存儲在Web API 中:
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
B) 調用堆棧執行Promise.resolve(true).then(resolve)并安排承諾解決方案。resolved()回調存儲在Web API 中:
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
C)承諾立即解決,計時器立即超時。因此,定時器回調timeout()被排入任務隊列,promise 回調resolve()被排入作業隊列:
D)現在是有趣的部分:事件循環優先于任務出列作業。事件循環resolve()從作業隊列中取出承諾回調并將其放入調用堆棧中。然后調用堆棧執行承諾回調resolve():
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
'Resolved!' 記錄到控制臺。
E) 最后,事件循環將計時器回調timeout()從任務隊列中出列到調用堆棧中。然后調用堆棧執行定時器回調timeout():
setTimeout(function timeout() {
console.log('Timed out!');
}, 0);
Promise.resolve(1).then(function resolve() {
console.log('Resolved!');
});
'Timed out!' 記錄到控制臺。
調用堆棧為空。腳本執行已完成。
4. 總結
為什么立即解決的承諾比立即計時器處理得更快?
由于事件循環優先級使作業隊列(存儲已履行的承諾的回調)中的作業優先于任務隊列(存儲超時setTimeout()回調)中的任務。
感謝各位的閱讀!關于“web中Promise.resolve().then(callback)比setTimeout(callback,0)更快的原因是什么”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。