我們首先知道,promise的then返回的始終是一個(gè)新promise权谁。那么就存在下述情況
let aPromise = new Promise((resolve,reject)=>{
resolve('aPromise')
})
aPromise.then(res=>'bPromise')
aPromise.then(res=>{console.log(res)}) // 實(shí)際上打印的是'aPromise'
then不是改變aPromise的內(nèi)容,而是始終返回新promise憋沿。
如此旺芽,當(dāng)我們要寫(xiě)一個(gè)循環(huán)體的時(shí)候。就需要一個(gè)游標(biāo)來(lái)記錄每次執(zhí)行完的then辐啄。
let delayPrint = (i = 1000) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(i);
resolve('ok:'+i)
}, 1000)
})
}
let forbody = Promise.resolve('begin');
for (let i = 1; i <= 5; i++) {
forbody = forbody.then(res=>{
return delayPrint(i);
})
}
我們的forbody每次重新記錄forbody.then返回的新promise采章。這樣下次執(zhí)行forbody.then的時(shí)候總能記錄正確的位置。利用這一特性壶辜,我們可以制造循環(huán)體悯舟。上述代碼可以依次打印1
,2
,3
,4
,5
。需要注意的是如果把console.log(i)放入then中砸民,變成console.log(res)會(huì)存在一個(gè)業(yè)務(wù)位置的問(wèn)題图谷。區(qū)別在于打印完5
后立即結(jié)束翩活,還是會(huì)再執(zhí)行下一個(gè)而不打印。原因時(shí)i=5時(shí)執(zhí)行完成后還會(huì)return一個(gè)delayPrint便贵,相當(dāng)于多執(zhí)行了一次菠镇。雖然沒(méi)有下次的then。
也有一些比較丑陋的解決方案承璃。如
let forbody = Promise.resolve('begin');
for (let i = 1; i <= 5; i++) {
forbody = forbody.then(res=>{
i!=5 && return delayPrint(i*1000);
})
}
改良方案利耍,用其他方式實(shí)現(xiàn)循環(huán)體
面對(duì)定長(zhǎng)的的循環(huán)體】猓可以用遍歷數(shù)組 + Promise.all的方式來(lái)實(shí)現(xiàn)隘梨。
使用這種方式很直觀,并且在執(zhí)行完成后能一次性得到所有的resolve