中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解JavaScript 事件循環中的微任務Microtask

發布時間:2021-09-30 11:09:02 來源:億速云 閱讀:101 作者:柒染 欄目:web開發

如何理解JavaScript 事件循環中的微任務Microtask,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

微任務(Microtask)

Promise 的處理程序(handlers).then、.catch 和 .finally 都是異步的。

即便一個 promise 立即被 resolve,.then、.catch 和 .finally 下面  的代碼也會在這些處理程序(handler)之前被執行。

示例代碼如下:

let promise = Promise.resolve();  promise.then(() => alert("promise done!"));  alert("code finished"); // 這個 alert 先顯示

如果你運行它,你會首先看到 code finished,然后才是 promise done。

這很奇怪,因為這個 promise 肯定是一開始就完成的。

為什么 .then 會在之后才被觸發?這是怎么回事?

微任務隊列(Microtask queue)

異步任務需要適當的管理。為此,ECMA 標準規定了一個內部隊列 PromiseJobs,通常被稱為“微任務隊列(microtask queue)”(V8  術語)。

如 規范[1] 中所述:

  • 隊列(queue)是先進先出的:首先進入隊列的任務會首先運行。

  • 只有在 JavaScript 引擎中沒有其它任務在運行時,才開始執行任務隊列中的任務。

或者,簡單地說,當一個 promise 準備就緒時,它的 .then/catch/finally  處理程序(handler)就會被放入隊列中:但是它們不會立即被執行。當 JavaScript 引擎執行完當前的代碼,它會從隊列中獲取任務并執行它。

這就是為什么在上面那個示例中 "code finished" 會先顯示。

如何理解JavaScript 事件循環中的微任務Microtask

Promise 的處理程序(handler)總是會經過這個內部隊列。

如果有一個包含多個 .then/catch/finally  的鏈,那么它們中的每一個都是異步執行的。也就是說,它會首先進入隊列,然后在當前代碼執行完成并且先前排隊的處理程序(handler)都完成時才會被執行。

如果執行順序對我們很重要該怎么辦?我們怎么才能讓 code finished 在 promise done 之后運行呢?

很簡單,只需要像下面這樣使用 .then 將其放入隊列:

Promise.resolve()   .then(() => alert("promise done!"))   .then(() => alert("code finished"));

現在代碼就是按照預期執行的。

未處理的 rejection

還記得 使用 promise 進行錯誤處理[2] 一章中的 unhandledrejection 事件嗎?

現在,我們可以確切地看到 JavaScript 是如何發現未處理的 rejection 的。

如果一個 promise 的 error 未被在微任務隊列的末尾進行處理,則會出現“未處理的 rejection”。

正常來說,如果我們預期可能會發生錯誤,我們會在 promise 鏈上添加 .catch 來處理 error:

let promise = Promise.reject(new Error("Promise Failed!")); promise.catch(err => alert('caught'));  // 不會運行:error 已經被處理 window.addEventListener('unhandledrejection', event => alert(event.reason));

但是如果我們忘記添加 .catch,那么,微任務隊列清空后,JavaScript 引擎會觸發下面這事件:

let promise = Promise.reject(new Error("Promise Failed!"));  // Promise Failed! window.addEventListener('unhandledrejection', event => alert(event.reason));

如果我們遲一點再處理這個 error 會怎樣?例如:

let promise = Promise.reject(new Error("Promise Failed!")); setTimeout(() => promise.catch(err => alert('caught')), 1000);  // Error: Promise Failed! window.addEventListener('unhandledrejection', event => alert(event.reason));

現在,如果我們運行上面這段代碼,我們會先看到 Promise Failed!,然后才是 caught。

如果我們并不了解微任務隊列,我們可能會想:“為什么 unhandledrejection  處理程序(handler)會運行?我們已經捕獲(catch)并處理了 error!”

但是現在我們知道了,當微任務隊列中的任務都完成時,才會生成 unhandledrejection:引擎會檢查 promise,如果 promise  中的任意一個出現 "rejected" 狀態,unhandledrejection 事件就會被觸發。

在上面這個例子中,被添加到 setTimeout 中的 .catch 也會被觸發。只是會在 unhandledrejection  事件出現之后才會被觸發,所以它并沒有改變什么(沒有發揮作用)。


Promise 處理始終是異步的,因為所有 promise 行為都會通過內部的 "promise jobs" 隊列,也被稱為“微任務隊列”(V8  術語)。

因此,.then/catch/finally 處理程序(handler)總是在當前代碼完成后才會被調用。

如果我們需要確保一段代碼在 .then/catch/finally 之后被執行,我們可以將它添加到鏈式調用的 .then 中。

在大多數 JavaScript 引擎中(包括瀏覽器和 Node.js),微任務(microtask)的概念與“事件循環(event  loop)”和“宏任務(macrotasks)”緊密相關。由于這些概念跟 promise 沒有直接關系,所以我們將在 圖解 JavaScript  事件循環:微任務和宏任務 一文中對它們進行介紹。

看完上述內容,你們掌握如何理解JavaScript 事件循環中的微任務Microtask的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

靖州| 若尔盖县| 本溪| 永年县| 临城县| 洛扎县| 仙桃市| 南皮县| 灵川县| 广南县| 云南省| 西乌| 濉溪县| 海原县| 彰武县| 新化县| 临洮县| 澜沧| 昭苏县| 鄯善县| 花莲县| 赤峰市| 宜兰县| 皋兰县| 西丰县| 迭部县| 沙洋县| 利辛县| 鄂尔多斯市| 宾阳县| 郴州市| 天门市| 咸阳市| 如皋市| 都安| 贺州市| 女性| 广州市| 彭水| 清水河县| 类乌齐县|