all方法 手写promise_「超全」手写 Promise 的相关方法

「超全」手写 Promise 的相关方法

原文发布在: 手写 Promise 的相关方法.

摘要

Promise 作为 JS 社区的异步解决方案, 为开发者提供了. then(),Promise.resolve(),Promise.reject() 等基本方法. 除此之外, 为了更方便地组合和控制多个的 Promise 实例, 也提供了. all(),.race() 等方法.

本文会在 Promise 的基本方法上, 手动实现更高级的方法, 来加深对 Promise 的理解:

实现 Promise.all

实现 Promise.race

实现 Promise.any

实现 Promise.allSettled

实现 Promise.finally

完整代码和用例请到 GitHub.com/dongyuanxin/diy-promise.

实现 Promise.all

过程

Promise.all(iterators) 返回一个新的 Promise 实例. iterators 中包含外界传入的多个 promise 实例.

对于返回的新的 Promise 实例, 有以下两种情况:

如果传入的所有 promise 实例的状态均变为 fulfilled, 那么返回的 promise 实例的状态就是 fulfilled, 并且其 value 是 传入的所有 promise 的 value 组成的数组.

如果有一个 promise 实例状态变为了 rejected, 那么返回的 promise 实例的状态立即变为 rejected.

代码实现

实现思路:

传入的参数不一定是数组对象, 可以是 "遍历器"

传入的每个实例不一定是 promise, 需要用 Promise.resolve() 包装

借助 "计数器", 标记是否所有的实例状态均变为 fulfilledPromise.myAll=function(iterators){

constpromises=Array.from(iterators);

constnum=promises.length;

constresolvedList=newArray(num);

letresolvedNum=0;

returnnewPromise((resolve,reject)=>{

promises.forEach((promise,index)=>{

Promise.resolve(promise)

.then(value=>{

// 保存这个 promise 实例的 value

resolvedList[index]=value;

// 通过计数器, 标记是否所有实例均 fulfilled

if(++resolvedNum===num){

resolve(resolvedList);

}

})

.catch(reject);

});

});

};

实现 Promise.race

过程

Promise.race(iterators) 的传参和返回值与 Promise.all 相同. 但其返回的 promise 的实例的状态和 value, 完全取决于: 传入的所有 promise 实例中, 最先改变状态那个 (不论是 fulfilled 还是 rejected).

代码实现

实现思路:

某传入实例

pending -> fulfilled

时, 其 value 就是 Promise.race 返回的 promise 实例的 value

某传入实例 pending -> rejected 时, 其 error 就是 Promise.race 返回的 promise 实例的 errorPromise.myRace=function(iterators){

constpromises=Array.from(iterators);

returnnewPromise((resolve,reject)=>{

promises.forEach((promise,index)=>{

Promise.resolve(promise)

.then(resolve)

.catch(reject);

});

});

};

实现 Promise.anyPromise.any=function(iterators){

constpromises=Array.from(iterators);

constnum=promises.length;

constrejectedList=newArray(num);

letrejectedNum=0;

returnnewPromise((resolve,reject)=>{

promises.forEach((promise,index)=>{

Promise.resolve(promise)

.then(value=>resolve(value))

.catch(error=>{

rejectedList[index]=error;

if(++rejectedNum===num){

reject(rejectedList);

}

});

});

});

};constformatSettledResult=(success,value)=>

success

?{status:"fulfilled",value}

:{status:"rejected",reason:value};

Promise.allSettled=function(iterators){

constpromises=Array.from(iterators);

constnum=promises.length;

constsettledList=newArray(num);

letsettledNum=0;

returnnewPromise(resolve=>{

promises.forEach((promise,index)=>{

Promise.resolve(promise)

.then(value=>{

settledList[index]=formatSettledResult(true,value);

if(++settledNum===num){

resolve(settledList);

}

})

.catch(error=>{

settledList[index]=formatSettledResult(false,error);

if(++settledNum===num){

resolve(settledList);

}

});

});

});

};newPromise(resolve=>{

setTimeout(()=>resolve(1),1000);

})

.then(value=>console.log(Date.now()))

.catch(error=>console.log(Date.now()));newPromise(resolve=>{

setTimeout(()=>resolve(1),1000);

}).finally(()=>console.log(Date.now()));Promise.prototype.finally=function(cb){

returnthis.then(

value=>Promise.resolve(cb()).then(()=>value),

error=>

Promise.resolve(cb()).then(()=>{

throwerror;

})

);

};GitHub.com/tc39/proposal-promise-allSettled

GitHub.com/matthew-andrews/Promise.prototype.finally

来源: http://www.jianshu.com/p/b4e8295c9bf3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值