摘要:現實中是這樣的執行結果為結果告訴我們,是單線程沒錯,不過不是逐行同步執行。搜索了很多官方個人博客得到了一堆詞引擎主線程事件表事件隊列宏任務微任務,徹底懵逼。。。以此規則不停的執行下去就是我們所聽到的事件循環。
都知道javascript是單線程,那么問題來了,既然是單線程順序執行,那怎么做到異步的呢?
setTimeout(function() { console.log(1); }); new Promise(function(resolve, reject) { console.log(2) resolve(3) }).then(function(val) { console.log(val); }) console.log(4) //執行結果為 2、4、3、1
結果告訴我們,js是單線程沒錯,不過不是逐行同步執行。
那我們就來解析一下既然有異步,那順序是怎樣的?這些執行順序規則就是理解eventLoop的要點,繼續往下。
上圖為我錄制的chrome控制代碼臺執行順序,雖然能看出執行順序但我們還是懵逼的,我們不知道規則,不懂就要問。
搜索了很多官方、個人博客得到了一堆詞:js引擎、主線程、事件表、事件隊列、宏任務、微任務,徹底懵逼。。。
不急不急一個個來,我們進入刨根問底狀態
js引擎總結一句話就是解析優化代碼 **制定執行規則 具體規則往下看
主線程總結一句話執行js引擎優化并排列順序后的代碼
事件表(event table)執行代碼過程中,異步的回調,例如(setTimeout,ajax回調)注冊回調事件到event table
事件隊列當事件回調結束,事件表(event table)會將事件移入到事件隊列(event queue)
宏任務和微任務事件 | 瀏覽器 | node |
---|---|---|
I/O | ? | ? |
setTimeout | ? | ? |
setInterval | ? | ? |
setImmediate | ? | ? |
requestAnimationFrame | ? | ? |
事件 | 瀏覽器 | node |
---|---|---|
I/O | ? | ? |
process.nextTick | ? | ? |
MutationObserver | ? | ? |
Promise.then catch finally | ? | ? |
很多博客是這樣說的:
瀏覽器會不斷從task隊列中按順序取task執行,每執行完一個task都會檢查microtask隊列是否為空(執行完一個task的具體標志是函數執行棧為空),如果不為空則會一次性執行完所有microtask。然后再進入下一個循環去task隊列中取下一個task執行
說實話不是太理解,那么我就以自己的方式去學習和理解
為了更好的理解我們再看代碼
console.log("1"); setTimeout(function() { console.log("2"); new Promise(function(resolve) { console.log("3"); resolve(); }).then(function() { console.log("4") }) }) new Promise(function(resolve) { console.log("5"); resolve(); }).then(function() { console.log("6") }) setTimeout(function() { console.log("7"); new Promise(function(resolve) { console.log("8"); resolve(); }).then(function() { console.log("9") }) }) //執行結果:1、5、6、2、3、4、7、8、9
有圖為證我沒騙你
再來個動圖我們具體看看瀏覽器的執行順序
首先js引擎,區分是直接執行(同步代碼),再執行異步代碼,如果是異步再區分是宏任務還是微任務,分別放入兩個任務隊列,然后開始執行,每執行完一個宏任務,掃一遍微任務隊列并全部執行,此時形成一次eventLoop循環。以此規則不停的執行下去就是我們所聽到的事件循環。
我再補充一點,可以理解js引擎一開始把整個script當做一個宏任務,這樣里邊的就更容易理解了,開始就執行script宏任務,解析到宏任務里邊又包含同步代碼和異步代碼(宏任務和微任務)依次執行順序形成eventLoop。
歡迎吐槽點贊評論!
文章參考學習:
https://www.jianshu.com/p/12b...
https://juejin.im/post/59e85e...
https://segmentfault.com/a/11...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/101063.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不是多線程呢?這樣還能提...
閱讀 1352·2021-09-22 15:09
閱讀 2673·2021-08-20 09:38
閱讀 2412·2021-08-03 14:03
閱讀 876·2019-08-30 15:55
閱讀 3381·2019-08-30 12:59
閱讀 3558·2019-08-26 13:48
閱讀 1897·2019-08-26 11:40
閱讀 676·2019-08-26 10:30