摘要:關于和,因為本身就是的語法糖。實際上是一個讓出線程的標志。隊列清空,進入執行棧,打印,程序運行完畢。完整結果如下該結果基于版本。因為標準有所改變,所以稍老版本的瀏覽器結果可能不一致。
任務隊列
首先我們要知道關于JavaScript的一些規則:
JavaScript是被設計成單線程的
JavaScript的任務分為同步任務和異步任務
同步任務都在主線程上執行,形成一個執行棧。當主線程執行完之后,運行微任務(micro-task)隊列的任務直到為空,更新UI渲染(會根據瀏覽器的邏輯,決定要不要馬上執行更新),然后再運行宏任務(macro-task)隊列的任務直到為空......流程如下:
(主線程上的執行棧同步任務,可以視為是第一個macro-task隊列) macro-task -> micro-task(如果存在) -> 更新UI渲染
如此無限循環上面的流程,是為JavaScript的Event Loop機制。
宏任務宏任務(macro-task),宏任務隊列可以有一個或者多個。每個任務都有一個任務源(task source),源自同一個任務源的 task 必須放到同一個任務隊列,從不同源來的則被添加到不同隊列。
宏任務:script(全局任務), setTimeout, setInterval, setImmediate, I/O, UI rendering.
微任務微任務(micro-task),微任務在渲染更新前,macro-task之后執行。
關于async和await,因為async await 本身就是promise+generator的語法糖。所以await后面的代碼是microtask。實際上await是一個讓出線程的標志。await后面的表達式會先執行一遍,將await后面的代碼加入到microtask中,然后就會跳出整個async函數來執行后面的代碼。
微任務:process.nextTick, Promise, Object.observer, MutationObserver,await.
舉例async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); } async function async2() { console.log("async2"); } console.log("script start"); setTimeout(function () { console.log("setTimeout"); }, 0) async1(); new Promise(function (resolve) { console.log("promise1"); resolve(); }).then(function () { console.log("promise2"); }); console.log("script end");
流程如下:
console打印script start
setTimeout,是異步宏任務,進入macro-task setTimeout隊列
async1(), async await函數,在await之前是同步任務,直接執行,打印async1 start
await async2(),await后面的表達式會先執行一遍,打印async2
await 下面的代碼視為promise.then,進入micro-task promise隊列,跳出async1()
new Promise,promise內,.then之前的代碼是直接執行的,所以打印promise1
.then內函數進入micro-task promise隊列后
console,直接打印script end
主線程執行棧運行完并清空了,micro-task進入執行棧,分別按順序執行打印async1 end 和 promise2。
micro-task隊列清空,macro-task進入執行棧,打印setTimeout,程序運行完畢。
完整結果如下:
/** *script start *async1 start *async2 *promise1 *script end *async1 end *promise2 *setTimeout */
該結果基于chrome 版本 72.0.3626.121。因為async await標準有所改變,所以稍老版本的瀏覽器結果可能不一致。
參考:
https://jakearchibald.com/201...
https://github.com/Advanced-F...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109013.html
摘要:如果當前沒有事件也沒有定時器事件,則返回。相關資料關于的架構及設計思路的事件討論了使用線程池異步運行代碼。下一篇初窺事件機制的實現二中定時器的實現 在瀏覽器中,事件作為一個極為重要的機制,給予JavaScript響應用戶操作與DOM變化的能力;在Node.js中,事件驅動模型則是其高并發能力的基礎。 學習JavaScript也需要了解它的運行平臺,為了更好的理解JavaScript的事...
摘要:事件循環了解了在引擎中是如何工作了之后,來看下如何使用異步回調函數來避免代碼。從回調函數被放入后秒鐘,把移到中。由于事件循環持續地監測調用棧是否已空,此時它一注意到調用棧空了,就調用并創建一個新的調用棧。 聽多了JavaScript單線程,異步,V8,便會很想去知道JavaScript是如何利用單線程來實現所謂的異步的。我參考了一些文章,了解到一個很重要的詞匯:事件循環(Event L...
摘要:階段有兩個主要功能也會執行時間定時器到達期望時間的回調函數執行事件循環列表里的函數當進入階段并且沒有其余的定時器,那么如果事件循環列表不為空,則迭代同步的執行隊列中的函數。如果沒有,則等待回調函數進入隊列并立即執行。 Event Loop 本文以 Node.js 為例,講解 Event Loop 在 Node.js 的實現,原文,JavaScript 中的實現大同小異。 什么是 Eve...
摘要:的宿主最開始本身就是瀏覽器,處理用戶的交互事件。既然是單線程的,那就意味著任務需要排隊,只有前一個任務執行完畢,下一個任務才能開始,于是就有了任務隊列。事件循環有兩種用于瀏覽上下文的事件循環和用于的事件循環。 最近看到Event Loop這個詞出現的頻率有點高,于是查閱各方資料在此記錄一下。 先不說概念,我們來看段代碼: console.log(script start); setT...
js異步歷史 一個 JavaScript 引擎會常駐于內存中,它等待著我們把JavaScript 代碼或者函數傳遞給它執行 在 ES3 和更早的版本中,JavaScript 本身還沒有異步執行代碼的能力,引擎就把代碼直接順次執行了,異步任務都是宿主環境(瀏覽器)發起的(setTimeout、AJAX等)。 在 ES5 之后,JavaScript 引入了 Promise,這樣,不需要瀏覽器的安排,J...
摘要:曾經的理解首先,是單線程語言,也就意味著同一個時間只能做一件事,那么為什么不是多線程呢這樣還能提高效率啊假定同時有兩個線程,一個線程在某個節點上編輯了內容,而另一個線程刪除了這個節點,這時瀏覽器就很懵逼了,到底以執行哪個操作呢所以,設計者把 Event Loop曾經的理解 首先,JS是單線程語言,也就意味著同一個時間只能做一件事,那么 為什么JavaScript不是多線程呢?這樣還能提...
閱讀 3469·2023-04-25 21:43
閱讀 3096·2019-08-29 17:04
閱讀 797·2019-08-29 16:32
閱讀 1533·2019-08-29 15:16
閱讀 2142·2019-08-29 14:09
閱讀 2731·2019-08-29 13:07
閱讀 1623·2019-08-26 13:32
閱讀 1320·2019-08-26 12:00