本文一步一步深刻解讀 Promise 的註冊和執行過程,讀懂這幾段代碼,Promise 的註冊和執行過程你都將所向披靡,再也不話下~~~~。你就是 Promise 大神!~~。
更全解析文章:juejin.im/post/5dc028…promise
本文已代碼解讀的方式來學習整個過程。這裏提供了四段代碼,若是你都能理解清楚,正確的說出output過程,那麼厲害大牛如你,Promise 的執行過程瞭如指掌。微信
好多大牛已經熟悉了,固然了,並非全部的人都能理解這幾段代碼,那麼咱們就一塊兒來看看吧~數據結構
本文會依次解析這幾段代碼,最後給出 Promise 的終極執行過程。異步
new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
.then(() => {
console.log("外部第一個then");
return new Promise((resolve, reject) => {
console.log("內部promise");
resolve();
})
.then(() => {
console.log("內部第一個then");
})
.then(() => {
console.log("內部第二個then");
});
})
.then(() => {
console.log("外部第二個then");
});
複製代碼
這個輸出仍是比較簡單的,外部第一個 new Promise 執行,執行完 resolve ,而後執行外部第一個 then 。外部第一個 then 方法裏面 return 一個 Promise,這個return ,表明 外部的第二個 then 的執行須要等待 return 以後的結果。固然會先執行完內部兩個 then 以後,再執行 外部的第二個 then ,機智如你,徹底正確。函數
output:
外部promise
外部第一個then
內部promise
內部第一個then
內部第二個then
外部第二個thenoop
new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
.then(() => {
console.log("外部第一個then");
new Promise((resolve, reject) => {
console.log("內部promise");
resolve();
})
.then(() => {
console.log("內部第一個then");
})
.then(() => {
console.log("內部第二個then");
});
})
.then(() => {
console.log("外部第二個then");
});
複製代碼
這段代碼和第一段代碼就相差一個 return ,然而結果確是不同的。post
那這個怎麼理解呢?學習
咱們核心要看 then 的回調函數是啥時候註冊的,咱們知道,事件機制是 「先註冊先執行」,即數據結構中的 「隊列」 的模式,first in first out。那麼重點咱們來看下他們誰先註冊的。ui
外部的第二個 then 的註冊,須要等待 外部的第一個 then 的同步代碼執行完成。 當執行內部的 new Promise 的時候,而後碰到 resolve,resolve 以後須要執行的動做是一個微任務異步執行,那麼天然要先執行完同步任務,好比以下:spa
new Promise((resolve, reject) => {
resolve();
console.log(1111);
})
.then(() => {
consle.log(2222);
})
複製代碼
這個代碼顯然優先執行 111,在執行 2222。
同理回到上面的代碼,內部的 resolve 以後,固然是先執行內部的 new Promise 的第一個 then 的註冊,這個 new Promise執行完成,當即同步執行後面的 .then 的註冊。
然而這個內部的第二個 then 是須要第一個 then 的的執行來決定的,而第一個 then 的回調是沒有執行,僅僅只是執行了同步的 .then 方法的註冊,因此會進入等待狀態。
這個時候,外部的第一個 then 的同步操做已經完成了,而後開始註冊外部的第二個 then,此時外部的同步任務也都完成了。同步操做完成以後,那麼開始執行微任務,咱們發現 內部的第一個 then 是優先於外部的第二個 then 的註冊,因此會執行完內部的第一個 then 以後,而後註冊內部的第二個 then ,而後執行外部的第二個 then ,而後再執行內部的第二個 then。
output:
外部promise
外部第一個then
內部promise
內部第一個then
外部第二個then
內部第二個then
new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
.then(() => {
console.log("外部第一個then");
let p = new Promise((resolve, reject) => {
console.log("內部promise");
resolve();
})
p.then(() => {
console.log("內部第一個then");
})
p.then(() => {
console.log("內部第二個then");
});
})
.then(() => {
console.log("外部第二個then");
});
複製代碼
這段代碼的差別,就是內部的 Promise 的代碼的寫法變了,再也不是鏈式調用。
這裏怎麼理解呢?
這裏在執行內部的 new Promise 的 resolve 執行完成以後,new Promise 以後的兩個同步 p.then 是兩個執行代碼語句,都是同步執行,天然是會同步註冊完。
兩種方式的最主要的區別是:
因此這裏的代碼執行就比較清晰了,內部都執行完成以後(由於都優先於外部的第二個 then 的註冊),再執行外部的第二個 then :
output:
外部promise
外部第一個then
內部promise
內部第一個then
內部第二個then
外部第二個then
let p = new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
p.then(() => {
console.log("外部第一個then");
new Promise((resolve, reject) => {
console.log("內部promise");
resolve();
})
.then(() => {
console.log("內部第一個then");
})
.then(() => {
console.log("內部第二個then");
});
})
p.then(() => {
console.log("外部第二個then");
});
複製代碼
這段代碼中,外部的註冊採用了非鏈式調用的寫法,根據上面的講解,咱們知道了外部代碼的 p.then 是並列同步註冊的。因此代碼在內部的 new Promise 執行完,p.then 就都同步註冊完了。
內部的第一個 then 註冊以後,就開始執行外部的第二個 then 了(外部的第二個 then 和 外部的第一個 then 都是同步註冊完了)。而後再依次執行內部的第一個 then ,內部的第二個 then。
output:
外部promise
外部第一個then
內部promise
外部第二個then
內部第一個then
內部第二個then
我相信,若是能看懂上面的四段代碼以後,對 Promise 的執行和註冊很是瞭解了。
若是仍是不太懂,麻煩多看幾遍,相信你必定能懂~~~~~~~~
核心思想:
Promise 的 then 的 註冊 和 執行 是分離的。
註冊 : 是徹底遵循 JS 的代碼的執行過程。
執行 : 先 同步,再 微任務 ,再 宏觀任務。
遵循 event loop的原理,Promise 控制了 then 的註冊時機。
只有分開理解上述,才能真正理解它們的執行順序~~~~~~~~~~~~~~~~
最後出一道題:
new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
.then(() => {
console.log("外部第一個then");
new Promise((resolve, reject) => {
console.log("內部promise");
resolve();
})
.then(() => {
console.log("內部第一個then");
})
.then(() => {
console.log("內部第二個then");
});
return new Promise((resolve, reject) => {
console.log("內部promise2");
resolve();
})
.then(() => {
console.log("內部第一個then2");
})
.then(() => {
console.log("內部第二個then2");
});
})
.then(() => {
console.log("外部第二個then");
});
複製代碼
你能知道輸出結果,且能解釋清楚嗎?
若是你以爲這篇內容對你有價值,請點贊,並關注咱們的官網和咱們的微信公衆號(WecTeam),每週都有優質文章推送: