18 JS的事件迴圈,以及微任務和巨集任務。
js執行機制:eventloop(事件迴圈),看了很多部落格的講解,我也想自己總結一些這個知識點。
JavaScript的事件分為同步任務和非同步任務
首先第一點,js永遠是單執行緒的,以後也是。
使用單執行緒原因:如果多執行緒,一個執行緒刪除元素,一個執行緒修改元素會造成混亂。
使用單執行緒問題:如果一個任務等待的時間非常久,在這中間會有cpu閒置,1會浪費時間,2會浪費資源。
解決辦法:同步和非同步。
同步任務:主執行緒執行的任務。
非同步任務:不進入主執行緒,而是進入任務佇列,任務佇列通知主執行緒,某個可以執行了,就可以執行。
(1)所有同步任務都在主執行緒上執行(console.log(),for迴圈,new Process裡面),形成一個執行棧(execution context stack)。
(2)主執行緒之外,還存在一個"任務佇列"(task queue)。只要非同步任務有了執行結果,就在"任務佇列"之中放置一個事件。
(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務佇列",看看裡面有哪些事件。那些對應的非同步任務,於是結束等待狀態,進入執行棧,開始執行。
"任務佇列":除了IO裝置的事件以外,還包括一些使用者產生的事件(比如滑鼠點選、頁面滾動等等)。只要指定過回撥函式,這些事件發生時就會進入"任務佇列",等待主執行緒讀取。
"回撥函式"(callback):就是那些會被主執行緒掛起來的程式碼。非同步任務必須指定回撥函式,當主執行緒開始執行非同步任務,就是執行對應的回撥函式。
JavaScript的任務分為微任務(Microtasks)和巨集任務(task)
0 涉及到的資料結構有什麼?
資料結構:1stack 執行棧。 2 巨集任務佇列。3 微任務佇列。
1 執行規則是什麼?
答:執行規則:
1 第一個巨集任務入棧執行,遇到巨集任務放在巨集任務佇列裡面,遇到微任務放在當前微任務佇列裡面,遇到同步程式碼放在棧裡面執行。(注意放的是回撥函式!)
2 第一個巨集任務執行完,會找到微任務佇列,給微任務佇列說,該你執行了,微任務佇列把自己佇列裡面的任務全部執行完。
3微任務佇列執行結束。如果還有巨集任務,就繼續執行巨集任務回到1。沒有的話就結束。
2 微任務巨集任務都有誰啊?
1巨集任務(macrotask): 1整個程式碼(scirpt),2定時器(setTimeout ,setImmediate),3事件繫結setInterval,4ajax,5回撥函式,6Node中fs可以進行非同步的I/O操作
2 微任務(microtask):promise.nextTick,promise.then(), async await。
3 直接執行的有:console.log(),new Process裡面的。
3 都是非同步程式碼為什麼還要區分巨集任務,微任務啊?如何區分巨集任務和微任務呢?劃分的標準是什麼?
在ES3以及以前的版本中,JavaScript本身沒有發起非同步請求的能力,也就沒有微任務的存在。在ES5之後,JavaScript引入了Promise
,這樣,不需要瀏覽器,JavaScript引擎自身也能夠發起非同步任務了。
兩者區別為:巨集任務是由宿主發起的,而微任務由JavaScript自身發起。
巨集任務(macrotask) | 微任務(microtask) | |
---|---|---|
誰發起的 | 宿主(Node、瀏覽器) | JS引擎 |
具體事件 | 1. script (可以理解為外層同步程式碼) 2. setTimeout/setInterval 3. UI rendering/UI事件 4. postMessage,MessageChannel 5. setImmediate,I/O(Node.js) |
1. Promise 2. MutaionObserver 3. Object.observe(已廢棄; Proxy 物件替代)4. process.nextTick(Node.js) |
誰先執行 | 後執行 | 先執行 |
會觸發新一輪Tick嗎 | 會 | 不會 |
- 巨集任務 Macrotasks就是參與了事件迴圈的非同步任務。
- 巨集任務 Macrotasks就是不參與事件迴圈的非同步任務。
- Chromium 自定義訊息
- Socket 或者檔案等 IO 訊息
- UI 相關的訊息
- 是個記憶體回收的清理任務,使用過 Java 的童鞋應該都很熟悉,只是在 JavaScript 這是V8內部呼叫的
- 就是普通的回撥,MutationObserver 也是這一類
- Callable
- 包括 Fullfiled 和 Rejected 也就是 Promise 的完成和失敗
- Thenable 物件的處理任務
3 為什麼整個程式碼(scirpt)在巨集任務裡面?
答:因為一開始需要一個執行機制啊,而且先把所有的同步程式碼執行完,非同步程式碼放入佇列。所以優先級別最高!
建議先看視訊(b站):https://www.bilibili.com/video/BV12Z4y1p7Zd?from=search&seid=15652075497796620445
https://www.bilibili.com/video/BV1Hp4y1Y7h7?from=search&seid=15652075497796620445
建議再看圖文版(知乎):https://zhuanlan.zhihu.com/p/26238030
詳解巨集任務和微任務(部落格園):https://www.cnblogs.com/mfyngu/p/11747533.html
掘金的兩個大佬:
https://juejin.cn/post/6903338967656366094
https://juejin.cn/post/6844903512845860872#heading-2
csdn:
https://blog.csdn.net/xiaojinguniang/article/details/82985471
https://blog.csdn.net/qq_40323256/article/details/104553150
學後練習:
https://blog.csdn.net/weixin_42420703/article/details/82790942
三個大佬的補充,我還沒有看完: