EventLoop是MS中的高頻問題,理解繁瑣,一步當心,步步入坑。html
一、EventLoop是什麼?
二、任務隊列是什麼?
三、同步任務和異步任務?
四、微任務和宏任務?
...
複製代碼
咱們都知道Js是單線程語言,即同一時間只能作一件事情,可是爲了協調各類事件、用戶交互、腳本加載、UI渲染和網絡處理等行爲,避免主線不阻塞,出現了EventLoop => ==事件循環==也就是咱們常說的 異步 的方案。前端
過程:git
在執行主線程的任務時,若是有異步任務,會進入到Event Table並註冊回調函數,當指定的事情完成後,
會將這個回調函數放到 callback queue 中
在主線程執行完畢以後,會去讀取 callback queue中的回調函數,進入主線程執行
不斷的重複這個過程,也就是常說的Event Loop(事件循環)了
複製代碼
事件循環是經過任務隊列的機制來進行協調的。一個EventLoop中,能夠有一個或者多個任務隊列(task queue),一個任務隊列即是一系列有序任務(task)的集合;每一個任務都有一個任務源(task source),源自同一個任務源的 task 必須放到同一個任務隊列,從不一樣源來的則被添加到不一樣隊列。github
在事件循環中,每進行一次循環操做稱爲 tick,每一次 tick 的任務處理模型是比較複雜的,但關鍵步驟以下:
一、在這次 tick 中選擇最早進入隊列的任務(oldest task),若是有則執行(一次)
二、檢查是否存在 Microtasks,若是存在則不停地執行,直至清空 Microtasks Queue
三、更新 render
四、主線程重複執行上述步驟
複製代碼
同步:必定要等任務執行完了,獲得結果,才執行下一個任務。同步會阻塞代碼運行,例如 alert
異步:異步任務會在異步任務有告終果後,將註冊的回調函數放入任務隊列中等待主線程空閒的時候(調用棧被清空),被讀取到棧內等待主線程的執行。。例如 setTimeout
複製代碼
異步並非同步,異步是單線程,異步指的是讓CPU暫時擱置當前請求的響應,處理下一個請求,當經過輪詢或其餘方式獲得回調通知後,開始運行。面試
同步就是我必須等到你的回覆,才能作出下一步響應。即個人操做是順序執行的,中間少了哪一步都不能夠,或者說中間哪一步出錯都不能夠,若是我沒有收到你的回覆,我就一直處於等待、也就是阻塞的狀態。ajax
異步則相反,對你響應的時間也不敏感,不管你返回仍是不返回,我都能繼續運行;你響應並返回了,我就繼續作以前的事情,你沒有響應,我就作其餘的事情。也就是說我不存在等待對方的概念,我就是非阻塞的。segmentfault
因此像setTimeOut定時任務、ajax請求都是須要必定的時間的,因此通常都是用異步方式,不會阻塞後邊代碼的執行,而是設置了定時時間以後、或發送了請求以後,就移動到單線程的任務隊列的最尾端,等後邊執行完以後再執行定時代碼或者ajax請求的回調函數內代碼。瀏覽器
注意:bash
異步並非Js同時執行兩段操做,它只是設定了定時的時間,而後放到任務隊列的最後面,而後去執行其餘操做,當設定的時間到了以後在把事件拿回來繼續執行。網絡
異步任務又分爲 宏任務(MacroTask) 跟 微任務(MicroTask),主要區別在於執行順序的不一樣。咱們都知道js應該是按照語句前後順序執行,在出現異步時,則發起異步請求,再接着往下執行,待異步結果返回後再接着執行。
注意:
這兩個任務分別維護一個隊列,均採用先進先出的策略進行執行!同步執行的任務都在宏任務上執行。
宏任務隊列macrotask一次只從隊列中取一個任務執行,執行完後就去執行微任務隊列中的任務;
微任務隊列中全部的任務都會被依次取出來執行,知道microtask queue爲空;
複製代碼
1.首先執行同步代碼,這屬於宏任務
2.當執行完全部同步代碼後,執行棧爲空,查詢是否有異步代碼須要執行
3.執行全部微任務
4.當執行完全部微任務後,若有必要會渲染頁面
5.而後開始下一輪EventLoop,執行宏任務中的異步代碼,也就是setTimeout中的回調函數
複製代碼
以前兜兜轉轉,老是忘記事件的執行順序。長時間不接觸,有些記憶愈加的淡忘。只能不斷重拾記憶,加深。