一道有意思并对你有帮助的Promise题
一道有意思的題
以下我的學(xué)習(xí)分析心路歷程,以及我自己又多加了幾道菜;希望對你有幫助
先上菜
new Promise((resolve, reject) => {console.log('promise1');resolve(); }).then(() => {console.log('then11');new Promise((resolve, reject) => {console.log('promise2');resolve();}).then(() => {console.log('then21');}).then(() => {console.log('then23');}); }).then(() => {console.log('then12'); });復(fù)制代碼分析第一道菜
- 第一次看到我做錯了,答案是
- 我的疑惑就是then12為什么在then21和then23之前,很奇怪。說明什么呢?我對Promise的內(nèi)部實現(xiàn)還不了解,那只能去看源碼了。在學(xué)習(xí)過程中,自己也嘗試改變了幾處,也貼上來吧,大家看看
看完后我的理解
先分析下面代碼
new Promise((resolve, reject) => {console.log('promise1');resolve(); }) 復(fù)制代碼-
第一步console.log('promise1'),這是第一個promise實例
-
第二步resolve(),他是一個異步,放入異步隊列中,取名異步1
-
第三步this.status 狀態(tài)是pending 接著執(zhí)行下面代碼
- 因為狀態(tài)是pending,將then方法回調(diào)函數(shù)加入執(zhí)行隊列(一個數(shù)組)等待執(zhí)行(專用來放then方法的數(shù)組),該then方法取名方法1
重點接著執(zhí)行什么?
并不是執(zhí)行.then(() => {console.log(then12)}),要記住的是then的參數(shù)方法執(zhí)行時機是當(dāng)前(屬于自己的)promise狀態(tài)改變才會執(zhí)行,誰改變resolve或者rejectd的執(zhí)行,那么這里then的promise哪里來,就是上面的方法1中來看他的return值 所以開始執(zhí)行異步1(我都有取名的,看?),第一個promise實例狀態(tài)變?yōu)镕ULFILLED
- 首先resolve()參數(shù)為undefind不是一個promise類型,所以執(zhí)行執(zhí)行隊列(一個數(shù)組),即方法1,也就是第一個then`的參數(shù)
- 因為狀態(tài)改變所以開始執(zhí)行方法1
- 第一步打印console.log('then11');
- 又新建了一個Promise,打印console.log('promise2');
- resolve();又一個異步,放入異步隊列中,取名異步2
- 然后因為新的promise它的狀態(tài)是pengding,所以() => {console.log('then21');}方法放入新的promise的執(zhí)行隊列的數(shù)組中(和上面一樣專用來放then方法的數(shù)組)
- 同理后面的then并不回執(zhí)行,它需要等待新的resolve的執(zhí)行,來改變狀態(tài)執(zhí)行then
重點2
- 因為方法1的沒有return,即return 一個undefined,但我們都知道then會默認(rèn)返回一個return new Promise((resolve, reject) => {})對象,所以這時候他是執(zhí)行了的一個異步操作resolve()取名異步3,
- 所以有了這個異步3,這個return的promise的狀態(tài)為pending,所以then(() => {console.log(then12)})加入到(專用來放then方法的數(shù)組)的執(zhí)行回調(diào)數(shù)組中
然后開始執(zhí)行異步隊列的函數(shù),有兩個異步2和異步3,先執(zhí)行異步2,接下來的操作和重點2是一樣的又會return new Promise((resolve, reject) => {}),又會有一個異步4resolve(),接著講then方法放入數(shù)組中,等待resolve()改變promise狀態(tài)來執(zhí)行then方法
- 所以在等待期間會執(zhí)行異步3,然后打印console.log(then12)
- 最后打印console.log(then23)
總結(jié)要點
- then(func)執(zhí)行時機是等待一個與它相關(guān)的promise的狀態(tài)改變
- then(func)中的func默認(rèn)會return new Promise((resolve, reject) => {resolve()})用于下一個then(func)
- 如果我們手動return 一個promise結(jié)果就會不同,看下面例子
再變個花樣
new Promise((resolve, reject) => {console.log('promise1');resolve(); //異步1 }).then(() => {console.log('then11');return new Promise((resolve, reject) => {console.log('promise2');resolve(); //異步2 }).then(() => {console.log('then21');//默認(rèn)resolve() 異步3}).then(() => {console.log('then23');//默認(rèn)resolve() 異步4}); }).then(() => {console.log('then12'); }); 復(fù)制代碼分析
- 看到一個then(func)中我們直接返回了一個promise,所以先加入第一異步2,并且要等待它相關(guān)的promise狀態(tài)改變,但是它狀態(tài)改變了,那就是等異步2的執(zhí)行,一旦執(zhí)行,接著就是() =>{console.log('then23'); //默認(rèn)resolve() 異步4}的執(zhí)行了,所以異步4先一步比異步5加入,也就先執(zhí)行了,
- 所以結(jié)果就是
我再來變個樣
new Promise((resolve, reject) => {console.log('promise1');resolve(); //異步1 }).then(() => {console.log('then11');new Promise((resolve, reject) => {console.log('promise2');resolve(); //異步2}).then(() => {console.log('then21'); //異步3}).then(() => {console.log('then23');//異步4});return Promise.resolve(1) //異步5 }).then(() => {console.log('then12'); }); 復(fù)制代碼分析一下這幾個異步就要能知道答案了
- console.log('promise1');
- 先加入異步1, 執(zhí)行后輸出console.log('then11'); console.log('promise2');
- 在加入異步2, 再加入異步5
- 先執(zhí)行異步2, console.log('then21'); 并將加入異步4
- 再執(zhí)行異步5, 但這個異步和下面的then不相關(guān),因為這邊隱藏的會再下加入一個resolve()(即異步6) 即這個異步5是這樣的resolve().then(res => { ... //resolve() 異步6 })
- 接著先執(zhí)行異步4, 輸出console.log('then23');
- 接著先執(zhí)行異步6, 輸出console.log('then12');
同樣發(fā)布在segmentfault
轉(zhuǎn)載于:https://juejin.im/post/5cde586651882525a20fd3cd
總結(jié)
以上是生活随笔為你收集整理的一道有意思并对你有帮助的Promise题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多元线性回归分析示例
- 下一篇: 【2022/01/27】thinkphp