這是今天一個朋友發給個人一個面試題,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
的執行機制密切相關了.函數
javascript
是一門單線程的語言, 這就意味着在執行代碼的時候, 都只有一個主線程來處理全部的任務.oop
咱們都知道 javascript
包括同步代碼和異步代碼, 那麼 javascript
是怎麼處理這兩種狀況的呢?spa
場所
, 同步的進入主線程,異步的進入 Event Table
並註冊函數Event Table
會將這個函數(回調函數)移入 Event Queue
Event Queue
讀取對應的函數,進入主線程執行Event Loop(事件循環)
這裏咱們引進了 Event Queue
事件隊列這一律念. 全部異步操做的回調都會進入到這裏. 而後等到主線程空閒, 就會從這裏調取回調執行.線程
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
執行結束, 檢查,不存在其餘, 結束.
以上。