Promise在循环体中需要注意的一些事项

我们首先知道,promise的then返回的始终是一个新promise。那么就存在下述情况

let aPromise = new Promise((resolve,reject)=>{
    resolve('aPromise')
})

aPromise.then(res=>'bPromise')
aPromise.then(res=>{console.log(res)}) // 实际上打印的是'aPromise'

then不是改变aPromise的内容,而是始终返回新promise。

如此,当我们要写一个循环体的时候。就需要一个游标来记录每次执行完的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。这样下次执行forbody.then的时候总能记录正确的位置。利用这一特性,我们可以制造循环体。上述代码可以依次打印1,2,3,4,5。需要注意的是如果把console.log(i)放入then中,变成console.log(res)会存在一个业务位置的问题。区别在于打印完5后立即结束,还是会再执行下一个而不打印。原因时i=5时执行完成后还会return一个delayPrint,相当于多执行了一次。虽然没有下次的then。

也有一些比较丑陋的解决方案。如

let forbody = Promise.resolve('begin');
for (let i = 1; i <= 5; i++) {
    forbody = forbody.then(res=>{
        i!=5 && return delayPrint(i*1000);
    })
}

改良方案,用其他方式实现循环体

面对定长的的循环体。可以用遍历数组 + Promise.all的方式来实现。
使用这种方式很直观,并且在执行完成后能一次性得到所有的resolve

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 再过几天就是3月8日了,原来的38是叫妇女节,以前有没有在香港电影里经常听到骂女人都会骂“死38”“臭38”。。。...
    同韩阅读 3,222评论 0 0
  • 在写作过程中,无论遇到什么的困难,哪怕已经写不下去,也要去挑战一切,完成目标。每天去写作,已经形成了一种心里反应,...
    千云变阅读 1,139评论 0 0

友情链接更多精彩内容