瀏覽器中的 Event Loop,巨集任務與微任務

2022-01-29 06:48:35 字數 1998 閱讀 3138

當我們執行 js **的時候其實就是往執行棧中放入函式,那麼遇到非同步**的時候該怎麼辦?其實當遇到非同步的**時,會被掛起並在需要執行的時候加入到 task(有多種 task) 佇列中。一旦執行棧為空,event loop 就會從 task 佇列中拿出需要執行的**並放入執行棧中執行,所以本質上來說 js 中的非同步還是同步行為。

不同的任務源會被分配到不同的 task 佇列中,任務源可以分為 微任務(microtask) 和 巨集任務(macrotask)。在 es6 規範中,microtask 稱為 jobs ,macrotask 稱為 task 。下面來看以下**的執行順序:

console.log('script start')

async

function

async1()

async

function

async2()

async1()

settimeout(

function

() , 0)

new promise(resolve =>)

.then(

function

() )

.then(

function

() )

console.log('script end')

//script start => async2 end => promise => script end => promise1 => promise2 => async1 end => settimeout

注意:新的瀏覽器中不是如上列印的,因為 await 變快了,具體內容可以往下看

首先先來解釋下上述**的 async 和 await 的執行順序。當我們呼叫 async1 函式時,會馬上輸出 async2 end,並且函式返回乙個 promise,接下來在遇到 await 的時候會就讓出線程開始執行 async1 外的**,所以我們完全可以把 await 看成是讓出執行緒的標誌。

然後當同步**全部執行完畢以後,就會去執行所有的非同步**,那麼又會回到 await 的位置執行返回的 promise 的 resolve 函式,這又會把 resolve 丟到微任務佇列中,接下來去執行 then 中的**,當兩個 then 中的**全部執行完畢以後,又會回到 await 的位置處理返回值,這時候你可以看成是 promise.resolve (返回值).then() ,然後 await 後的**全部被包裹進了 then 的**中,所以 console.log(' async1 end ') 會優先執行於 settimeout。

如果你覺得上面這段解釋還是有點繞,那麼我把 async 的這兩個函式改造成你一定能理解的**

new promise((resolve, reject) =>).then(() =>)
也就是說,如果 await 後面跟著 promise 的話,async1 end 需要等待三個 tick 才能執行到。那麼其實這個效能相對來說還是略慢的,所以 v8 團隊借鑑了 node 8 中的乙個 bug,在引擎底層將三次 tick 減少到了二次 tick。但是這種做法其實是違法了規範的,當然規範也是可以更改的,這是 v8 團隊的乙個 pr,目前已被同意這種做法。

所以 event loop 執行順序如下所示:

所以以上**雖然 settimeout 寫在 promise 之前,但是因為 promise 屬於微任務而 settimeout  屬於巨集任務,所以會有以上的列印。

微任務包括 process.nexttick ,promise ,mutationobserver 。

巨集任務包括 script , settimeout  ,setinterval ,setimmediate ,i/o ,ui rendering 。

這裡很多人會有個誤區,認為微任務快於巨集任務,其實是錯誤的。因為巨集任務中包括了 script ,瀏覽器會先執行乙個巨集任務,接下來有非同步**的話才會先執行微任務。

**自:yck的

瀏覽器的event loop

在瀏覽器的事件中,包含巨集任務和微任務。巨集任務有 setimmediate,settimeout,setinterval,i o,requestanimationframe,ui rendering,微任務有 promise,process.nexttick,object.observe,muta...

基礎篇 瀏覽器中的Event loop

在講event loop之前,我們先思考乙個問題 原因可能是如果js是多執行緒,在多個執行緒中處理dom就可能會發生問題 乙個執行緒新增新節點,另乙個執行緒中刪除節點 當然可以引入讀寫鎖解決這個問題 好了,接下來我們開始講event loop 簡單的說,就是js在執行的過程中會產生執行環境,這些執行...

瀏覽器大戰中的搜狗瀏覽器

abc 智慧型狂拼 紫光華宇,其中簡體中文全拼和智慧型 abc智慧型對於語句的輸入支援有限,而智慧型狂拼和紫光華宇詞儘管可以根據本地詞頻來智慧型新增詞語但本身詞庫更新慢,使用搜狗輸入法的原因是它每次上網時都會自動更新一些流行的詞語,使我們輸入更方便了。其實對於瀏覽器,我很少在意的,也不經常換,我自己...