当前位置: 首页 > 科技观察

Promise.allSettled的作用,如何实现一个Promise.allSettled

时间:2023-03-14 00:04:17 科技观察

本文转载自微信公众号《3分钟学会前端》,作者安姐。转载本文请联系三分钟学习前端公众号。简介本文从四个方面逐步介绍Promise.allSettled:Promise.all()的缺陷Promise.allSettled()简介Promise.allSettled()和Promise.all()的适用场景??Promise.all()缺陷我们在之前的一篇文章中问过面试官:Promise.all的用法、原理实现和错误处理都已经介绍过了。当我们使用Promise.all()来执行一个promise时,只要有一个promise失败,就会执行reject,被拒绝的是第一个抛出的错误信息。只有当所有的promise都被resolved,才会调用.then中的成功回调constp1=Promise.resolve(1)constp2=Promise。resolve(2)constp3=newPromise((resolve,reject)=>{setTimeout(reject,1000,'three');});Promise.all([p1,p2,p3]).then(values=>{控制台.log('resolve:',values)}).catch(err=>{console.log('reject:',err)})//reject:three注意:如果任何promise被拒绝,Promise.all会立即被拒绝,数组中其他未完成的承诺仍在执行中。Promise.all不采取任何措施取消它们的执行。但在大多数情况下,我们预计传入的一组承诺会失败或成功,可以获得每一个promise的执行结果。为此,ES2020引入了Promise.allSettled()Promise.allSettled()Promise.allSettled()可以获取数组中每一个promise的结果,无论constp1=Promise是否成功。解决(1)constp2=承诺。解决(2)constp3=newPromise((resolve,reject)=>{setTimeout(reject,1000,'three');});Promise.allSettled([p1,p2,p3]).then(values=>{console.log(values)})/*[{status:"fulfilled",value:1},{status:"fulfilled",value:2},{status:"rejected",reason:"three"}]*/当浏览器不支持时Promise.allSettled可以像这样被polyfilled:.allSettled=promises=>Promise.all(promises.map((promise)=>Promise.resolve(promise).then(resolveHandler,rejectHandler))//每个promise都需要用Promise.resolve包裹//防止传递非承诺);}//使用constp1=Promise.resolve(1)constp2=Promise.resolve(2)constp3=newPromise((resolve,reject)=>{setTimeout(reject,1000,'three');})constpromises=[p1,p2,p3]Promise.allSettled(promises).then(console.log)Promise.allSettled()和Promise.all()更适合各自的适用场景:Promise.allSettled()更适合able:互不依赖,其中任何一个都用reject,对其他没有影响期望知道每一个promise的执行结果。Promise.all()更适合:相互依赖,其中任何一个被拒绝,其他的都失去实际价值。手写的Promise.allSettled源码与Promise.all不同的是,当promise被reject后,我们不会直接reject,而是记录reject的值和对应的state'rejected';同样,当promise对象被resolved时,我们不仅仅记录值,还记录状态'fulfilled'当所有的promise对象都被fulfilled(resolved或rejected)后,我们将resolve所有promise执行结果arrayMyPromise.allSettled=function(promises){returnnewMyPromise((resolve,reject)=>{promises=Array.isArray(promises)?promises:[]letlen=promises.lengthconstargslen=len//如果传入空数组,则直接返回一个已解析的空数组promise对象if(len===0)returnresolve([])//将传入的参数转换成数组赋值给args变量letargs=Array.prototype.slice.call(promises)//计算当前是否所有的promises都执行了,resolveconstcompute=()=>{if(--len===0){resolve(args)}}functionresolvePromise(index,value){//判断传入是否为promise类型if(valueinstanceofMyPromise){constthen=value.thenthen.call(value,function(val){args[index]={status:'fulfilled',value:val}compute()},function(e){args[index]={status:'rejected',reason:e}compute()})}else{args[index]={状态:'已完成',价值:价值}compute()}}for(leti=0;i