手写 Promise.all 和 Promise.race

一、手写 Promise.all:

思路:

1. 首先 Promise.all返回的肯定是一个 promise对象,所以可以直接写 return new Promise((resolve, reject) => {});

2. 遍历传入的参数,用 Promise.resolve() 将参数的每一项进行一个包裹,使其变成一个 promise 对象,因为传入的参数不一定是 Promise 类型,可能不存在 then 方法;

3. 关键点是何时 resolve,可以声明一个变量,进行计数,当在每个 promise 对象 then 之后将 res放入到 result 中后,就可以将计数器 +1,当 +1 后与传入的参数的长度进行比较,如果相等就可以resolve了;

4. 如果期间有报错,就直接 reject 掉,后面的不再执行了,因为 Promise.all 就是所有都 resolve 才可以;

5. 官方规定Promise.all 接受的参数是一个可遍历的参数,所以未必是一个数组,可以用 Array.from() 转化一下;

6. 也可以不转化,直接使用for..of 进行遍历,因为凡是可遍历的变量应该都部署了itertetor方法,如果不转化的话,无法使用 for..in 进行遍历,所以用 for..of 遍历最安全。

引申:我们知道 Iterator 的接口就是提供了一个统一的访问机制,如果我们访问一个对象使用 Iterator API,需要不断的调用 next() 才能遍历完成;如果 Iterator 像 java那样提供一个hasNext()方法的话,那么我们可以通过while进行遍历,事实上 js 中是没有的。

之所以没有是因为ES6使用for...of...实现了对具有Symbol.iterator(可遍历)的数据结构的遍历,也就是说只要是包含Symbol.iterator属性的结构都可以使用for...of...进行遍历。

代码实现:

function promiseAll (args) {
    return new Promise((resolve, reject) => {
        const result = [];
        let iteratorIndex = 0;
        let fullCount = 0;
        for(const item of args) {
            let resultIndex = iteratorIndex;
            iteratorIndex += 1;
            Promise.resolve(item).then(res => {
                result[resultIndex] = res;
                fullCount += 1;
                if(fullCount == iteratorIndex) {
                    resolve(result)
                }
            }).catch(err => {reject(err)})
        }
        if(iteratorIndex === 0) {
            resolve(result)
        }
    })
}
if(!Promise.all) Promise.all = promiseAll

简易有瑕疵版:

Promise.prototype.all = function(promises) { 
    let results = [];
    let promiseCount = 0;
    let promisesLength = promises.length;
    return new Promise((resolve, reject) => {
        for(let i in promises) {
            Promise.resolve(promises[i]).then(res => {
                results[i] = res;
                if(++promiseCount === promisesLength) {
                    resolve(results) } 
            }).catch(err => {
                reject(err)
            })
        }
    })
}

二、手写Promise.race

因为Promise.race是只要有人能决议就返回谁,所以只要将all的计数器和逻辑判断全部去掉就好了

代码实现:

Promise.prototype.race = function(args) {
    return new Promise((resolve, reject) => {
        for(const p of args) {
            Promise.resolve(p).then(res => {
                resolve(res);
            }).catch(err => reject(err))
        }
    })
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值