Promise.all的实现和一些改进

Promise.all:

function isPromise(obj) {
  if (!!obj && (typeof(obj) === 'object' || typeof(obj) === 'function') && typeof(obj.then) === 'function') {
    return true
  } else {
    return false
  }
}
function newPromiseAll(arr) {
  let result = [];
  return new Promise( (resolve,reject) => {
    for(let i = 0; i < arr.length; i++){
      if(isPromise(arr[i])){
        arr[i].then(data => {
          result[i] = data;
          if(result.length === arr.length) {
            resolve(result)
          }
        }, reject)
      } else {
        result[i] = arr[i];
      }
    }    
  })
}

首先可以看到 Promise.all 返回了一个 Promise 对象。

Promise.all 是所有的 promise 都执行成功才执行resolve(当 result 的长度和数组长度一致时,resolve)有一个报错,就不执行。


那假如要改成,就算有一个报错,也能执行其他的 resolve。要怎么改呢?

function isPromise(obj) {
  if (!!obj && (typeof(obj) === 'object' || typeof(obj) === 'function') && typeof(obj.then) === 'function') {
    return true
  } else {
    return false
  }
}
function newPromiseAll(arr) {
  let result = [];
  return new Promise( (resolve,reject) => {
    for(let i = 0; i < arr.length; i++){
      if(isPromise(arr[i])){
        arr[i].then(data => {
          result[i] = data;
          if(result.length === arr.length) {
            resolve(result)
          }
        }).catch (err => {
          result[i] = err;
          if(result.length === arr.length) {
            resolve(result)
          }
        })
      } else {
        result[i] = arr[i];
      }
    }    
  })
}

首先将.then 里的第二个参数 reject去掉,这时当arr[i]报错时,就不会立即执行 reject然后执行最外层 Promise的 reject。

然后我们给.then 后面加上.catch,当 arr[i]执行失败时,会执行.catch 里的函数。然后我们在.catch 里将执行失败的结果也推进 result 里。

注意!!由于 arr[i]执行失败后执行了.catch,因此.catch 执行完后返回了一个新的Promise,且状态是 resolve!!所以他不会触发最外层的 Promise的 reject 了。


测试代码:

let p1 = new Promise((resolve, reject) => { 
		setTimeout(resolve, 1000, 'one'); 
	}); 
	let p2 = new Promise((resolve, reject) => { 
		setTimeout(resolve, 2000, 'two'); 
	});
	let p3 = new Promise((resolve, reject) => {
		setTimeout(resolve, 3000, 'three');
	});
	let p4 = new Promise((resolve, reject) => {
		setTimeout(resolve, 4000, 'four');
	});
	let p5 = new Promise((resolve, reject) => {
		reject('reject');
	});
	newPromiseAll([p1, p2, p3, p4, p5]).then(values => {
		console.log(values);
	}, reason => {
		console.log(reason)
	}); 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值