关于Promise.all的问题

来源:8-21 手写 Promise-all 和 race

几盎丶

2022-03-09

MyPromise.promiseAll = function(promises){
	return new Promise((resolve, reject)=>{
		if(!Array.isArray(promises)) throw new TypeError('promises is not a iterable')
		let resolvedCounter = 0
		let resolvedResult = []
		promises.forEach((p)=>{
			p.then(value => {
				resolvedCounter++
				resolvedResult.push(value)
				if(resolvedCounter === promises.length){
					return resolve(resolvedResult)
				}
			},reason => {
				return reject(reason)
			})
		})
	})
}

.push会导致返回结果数组的顺序错误

let p1 = Promise.resolve(1)
let p2 = Promise.resolve(2)
let a = Promise.promiseAll([p1,new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve(3)
    },3000)
}),p2])
// 输出
[1,2,3]
写回答

5回答

前端祭酒师

2022-05-05

  //   等待所有promise有结果
  static all(promiseList = []) {
  // 使用类数组的方案 手动控制length的长度 更加细粒度
    let result = {
      length: 0,
    };
    let length = promiseList.length;

    return new MyPromise((resolve, reject) => {
      promiseList.forEach((promiseItm, index) => {
        promiseItm.then((res) => {
          result[index] = res;
          result.length++;
          if (length === result.length) {
            resolve(Array.from(result));
          }
        });
      });
    });
  }


1
1
前端祭酒师
使用类数组 更细粒度的 手动控制length 返回的时候 Array.from()转化为数组
2022-05-05
共1条回复

zcj2022

2022-04-24

使用没let以前的方式,形成块级作用域来解决因为等待时间不同,导致返回值数组不能和传入的promise数组对应的问题

static all(promiseList = []) {
  const p1 = new MyPromise((resolve, reject) => {
    const result = [];
    const length = promiseList.length;
    let resolveCount = 0;

    promiseList.forEach((p, index) => {
      (function (index) { // 形成块级作用域
        p.then((res) => {
          result[index] = res;
          resolveCount++;
          if (resolveCount === length) {
            resolve(result);
          }
        }).catch((err) => reject(err));
      })(index);
    });
  });

  return p1;
}


0
1
前端祭酒师
回复错误 不好意思
2022-05-05
共1条回复

Tao_53755083

2022-03-21

MyPromise.all = function (list) {
  return new MyPromise((resolve, reject) => {
    const length = list.length
    const result = []
    let nub = 0

    list.forEach((p, i) => {
      p.then(data => {
	    nub++
        result[i] = data // 这里用下标存储 确保输入与输出 顺序一致
        
        if (nub === length) {
          resolve(result)
        }
      }).catch(err => {
        reject(err)
      })
    })
  })
 }

用下标就可以解决这个问题


0
1
嵇菁菁
应该不行吧,.then的执行是异步的,索引 i 是同步变化,i会在短时间内快速变成最大值length-1,你这样写会导致 data 每次存的都是 result[length-1]
2023-02-09
共1条回复

weixin_慕神0153302

2022-03-20

...

0
0

双越

2022-03-09

好问题。我考虑下这里怎么优化。


0
2
前端祭酒师
使用类数组 更细粒度的 手动控制length 返回的时候 Array.from()转化为数组
2022-05-05
共2条回复

一天时间高效准备前端技术一面 匹配大厂面试要求

针对时下面试高频考点,帮助新人js面试快速通关

4694 学习 · 1681 问题

查看课程