javascript的event loop事件循環

javascript的event loop事件循環

這是今天一個朋友發給個人一個面試題,javascript

感受還挺有意思的,java

寫個博客以供分享面試

 

先看看這個面試題目:promise

觀察下面的代碼,寫出輸出結果
異步

console.log('0') setTimeout(function () {  console.log('1'); }); new Promise(function(resolve,reject){  console.log('2')  resolve(3) }).then(function(val){  console.log(val) }) console.log(4)

輸出結果: 「0」 「2」 4 3 「1」async

 

今天主要是分析爲何輸出結果是這樣的?這就和 javascript 的執行機制密切相關了.函數

 


 

 

Event QueueEvent Loop

 

javascript 是一門單線程的語言, 這就意味着在執行代碼的時候, 都只有一個主線程來處理全部的任務.oop

咱們都知道 javascript 包括同步代碼和異步代碼, 那麼 javascript 是怎麼處理這兩種狀況的呢?spa

 

  • 同步和異步任務分別進入不一樣的執行 場所, 同步的進入主線程,異步的進入 Event Table 並註冊函數
  • 當指定的事情完成時, Event Table 會將這個函數(回調函數)移入 Event Queue
  • 主線程內的任務執行完畢爲空, 會去 Event Queue 讀取對應的函數,進入主線程執行
  • 上述過程會不斷重複, 也就是常說的 Event Loop(事件循環)

 

這裏咱們引進了 Event Queue 事件隊列這一律念. 全部異步操做的回調都會進入到這裏. 而後等到主線程空閒, 就會從這裏調取回調執行.線程

 


 

 

setTimeout

 

setTimeout 相信你們都有使用過, 能夠延時執行而且是異步執行的.

可是有時候咱們獲得的結果每每是代碼實際執行的時間比咱們想要延時執行的時間要久。這又是爲何呢?

這就和咱們以前所說的 Event Loop 有關了, 咱們能夠來具體看下 setTimeout 的執行步驟:

 

setTimeout(function () {
    asyncFn()
}, 1000);

syncFn()

 

  • asyncFn 將異步執行函數放在 Event Table, 而且開始計時
  • 開始執行 syncFn, 可是 syncFn 可能須要處理的內容不少, 執行時間超過 1 秒, 可是計時還在繼續
  • 計時到達 1 秒, setTimeout 延時完成, asyncFn 進入 Event Queue 事件隊列, 可是主線程還在執行, 因此只能等待
  • syncFn 執行完成, 此時 asyncFn 從事件隊列中進入主線程執行

因此有時候會出現代碼實際執行時間比延時時間長的狀況。

 


 

 

宏任務和微任務

 

以前咱們說過異步任務會進入到事件隊列中, 不一樣類型的任務會進入到不一樣的隊列中, 好比宏任務會進入到宏任務隊列中, 微任務會進入到微任務隊列中.

 

微任務:promise

宏任務:setTimeout、setInterval、setImmediate

 

咱們只要記住 噹噹前執行棧執行完畢時會馬上先處理全部微任務隊列中的事件,而後再去宏任務隊列中取出一個事件。同一次事件循環中,微任務永遠在宏任務以前執行

這時候咱們就能夠解釋一開始的代碼執行結果了:

 

  • 主線程執行按順序代碼
  • 遇到 setTimeout, 回調進入到宏任務隊列上
  • 遇到 Promise, 當即執行, then 函數進入到微任務隊列
  • 同步代碼執行結束, 主線程檢查是否存在微任務, 發現 then, 執行
  • 微任務執行完畢, 再去查找宏任務 setTimeout, 執行
  • setTimeout 執行結束, 檢查,不存在其餘, 結束.

 

 

 

以上。

相關文章
相關標籤/搜索