Promise與setTimeout你們應該都比較熟悉,不管是面試中仍是在實際編程它們都會常常出現。面試題中常常會將兩者放在一塊兒,加些console,讓你判斷輸出順序,這些熟悉可是又陌生的code讓人抓狂,到底順序是啥呢?js的世界裏沒有偶然,沒有僥倖,一切發生皆有其起因,今天讓咱們來一探究竟!java
很少說,直接上菜:面試
setTimeout(() => {
// t1
console.log(1);
}, 0);
// t2
console.log(2);
var promise1 = new Promise(function (resolve, reject) {
// t3
console.log(3);
resolve(4)
setTimeout(() => {
// t5
console.log(5);
});
var promise2 = Promise.resolve().then(() => {
t6
console.log(6);
});
}).then((res) => {
t4
console.log(res);
});
var promsie3 = Promise.resolve().then(() => {
// t7
console.log(7);
});
// t8
console.log(8);
複製代碼
你們能夠先在紙上寫下答案,咱們後面會一一拆解。這是一個大綜合,看着挺複雜,實際上是隻紙老虎,只要咱們能掌握其關鍵之處,便能很輕鬆的寫出輸出順序。ajax
首先,咱們先觀察題目,發現其代碼類型能夠分爲:setTimeout,Promise,全局下的console這三部分,再細緻一點其實就是同步任務與異步任務。這類問題的關鍵就是同步與異步任務的處理,好,讓咱們一一來分解。編程
javaScript是一門單線程語言(重點),這樣js事件循環就比如像是去銀行窗口窗口辦理業務,得排隊按順序去辦理,js事件也得按照註冊順序去執行。那萬一中間某一js事件執行時間很長,那是否是得一直等待嗎?固然這種狀況是存在的,不過咱們有相應的處理方式:異步任務。例如咱們瀏覽網頁時頁面發起的ajax請求,就是異步任務,這樣就不阻塞主頁面的瀏覽了。讓咱們用一張圖來講明這個過程:promise
1 單個異步任務bash
setTimeout(() => {
console.log('start');
}, 0);
console.log('end');
// end
// start
複製代碼
這個很簡單,你們應該一目瞭然
複製代碼
2 兩個相同方式的異步任務異步
setTimeout(() => {
// t2
console.log(0);
}, 0);
setTimeout(() => {
// t2
console.log(1);
}, 100);
// 0
// 1
複製代碼
對於延時器來講,執行到它時就開始計時,時間結束後將回調註冊到任務隊列中,因而任務隊列
中的順序是:t2,t1。因此輸出便爲0,1。
複製代碼
setTimeout與Promise混合在一塊兒的時候是什麼狀況呢?這裏咱們將異步任務再細分一下:微任務,宏任務。函數
讓咱們先來看看微任務與宏任務都有哪些:post
咱們用一張圖來講明:ui
在異步任務隊列裏微任務的優先級是高於宏任務的。在主線程任務結束後,會讀取異步任務隊列裏的任務,判斷微任務隊列裏是是否有任務,有的話執行。執行完畢後循環判斷。直至爲空,再執行宏任務隊列,循環往復。
好,關鍵之處咱們已經講解完畢,如今讓咱們回頭來看上面的那道‘大綜合’ 讓咱們逐步拆解:
好,如今咱們來整理下
好,如今咱們就能輕易的說出輸出的值了:2,3,8,6,4,7,1,5。小夥伴們,大家作對了嗎?
以上是我我的對整個過程的理解,在細節上或者一些過程上可能存在些誤差,不是很準確,僅供參考,加深理解。同窗們若是發現有不對的地方,歡迎批評指正。