Promise.all 使用 Promise 和数组方法进行模拟

问题描述 投票:0回答:1

我的任务是模拟 Promise.last 方法,我返回一个最后解决的 Promise

export const PROMISE1 = new Promise<string>((resolve, reject) => {
  setTimeout(() => resolve("First Promise Resolved"), 2000);
});
export const PROMISE2 = new Promise<string>((resolve, reject) => {
  setTimeout(() => resolve("Second Promise Resolved"), 3000);
});
export const PROMISE3 = new Promise<string>((resolve, reject) => {
  setTimeout(() => resolve("Third Promise Resolved"), 1000);
});

export const PROMISEARRAY = [PROMISE1, PROMISE2, PROMISE3];

export const isArrayEmpty = <T>(array: Promise<T>[]) => {
  if (!array.length) {
    throw new Error("Please type an array with at least one promise");
  }
};


const promiseAllArr = <T>(arrayOfPromises: Promise<T>[]): Promise<T[]> => {
  isArrayEmpty(arrayOfPromises);
  const arr = [] as T[];
  // return new Promise((resolve, reject) => {
  //   arrayOfPromises.forEach((element) => {
  //     element
  //       .then((value) => {
  //         arr.push(value);
  //         resolve(arr);
  //       })
  //       .catch((error) => reject(error));
  //   });
  // });
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arrayOfPromises.length; i++) {
      arrayOfPromises[i].then((value) => {
        arr.push(value);
        resolve(arr);
      });
    }
  });

const promiseLast = <T>(arrayOfPromises: Promise<T>[]): Promise<T> => {
  return promiseAllArr(arrayOfPromises).then((data) => {
    if (data.length) {
      console.log(data.length);
      return arrayOfPromises[arrayOfPromises.length - 1];
    }
    throw new Error("array error");
  });
};

const promiseLastResult = promiseLast(PROMISEARRAY);
console.log(promiseLastResult);

setTimeout(() => {
  promiseLastResult.then((data) => {
    console.log(data);
  });
}, 6000);



PromiseAll 模拟效果很好,但是当我尝试返回 PromiseLast 时,我得到了第一个已解决的承诺。如果是这样,为什么我会在 PromiseAll 中得到所有三个结果?

我已经尝试过 for 循环、forEach,但我不能使用 async/await -> 这将是我的下一个案例。

javascript async-await promise
1个回答
0
投票

代码中的主要问题是您的

promiseAllArr()
函数调用在第一个解决的承诺上解决。因此,它永远不会等待其余的完成,当然也不会等待最后一个。因此,您尝试在最后一个承诺完成之前检查结果。

这是我将如何实现这一点。请注意,我允许

promiseLast()
的参数是可迭代的(就像
Promise.all()
一样),因此它不必是数组。我已经用普通的 Javascript 实现了这个,所以它会在代码片段中运行。

function promiseLast(promises) {
    return new Promise((resolve, reject) => {
        let lenCntr = 0, resolveCntr = 0;
        for (let p of promises) {
            ++lenCntr;
            Promise.resolve(p).then(val => {
                ++resolveCntr;
                // if we're done with all of them, 
                // then this val is the last value we should resolve with
                if (resolveCntr === lenCntr) {
                    resolve(val);
                }
            }).catch(reject);
        }
        if (lenCntr === 0) {
            reject(new Error("promises argument must be an iterable with at least one element"));
        }
    });
}

const p1 = new Promise ((resolve, reject) => {
    setTimeout(() => resolve("First Promise Resolved"), 2000);
});
const p2 = new Promise ((resolve, reject) => {
    setTimeout(() => resolve("Second Promise Resolved"), 3000);
});
const p3 = new Promise ((resolve, reject) => {
    setTimeout(() => resolve("Third Promise Resolved"), 1000);
});

const promiseList = [p1, p2, p3];

promiseLast(promiseList).then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
});

关于实施的一些注意事项:

  1. 由于此实现可以接受任何任意可迭代(如

    Promise.all()
    ),因此它不假设存在
    .length
    属性。因此,它在迭代时计算长度。

  2. Promise.all()
    一样,如果任何承诺被拒绝,这将被拒绝。

  3. 这将可迭代值包装在

    Promise.resolve(p)
    中,以便迭代也可以包含普通值(再次就像使用
    Promise.all()
    一样),并且我们仍然可以对每个值调用
    .then()
    .catch()
    ,而不会出现错误或出现大量错误。类型检查和特殊代码。

© www.soinside.com 2019 - 2024. All rights reserved.