在数组遍历中正确使用promise(async/await)

2,819 阅读1分钟

首先分析如下代码:

function test() {
    const arr = [1, 2, 3, 4, 5];
    arr.forEach(async (item) => {
      const res = await new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(item);
        }, 2000);
      });
      console.log(res);
    });
    console.log("ss");
}

执行test函数时,arr.forEach会生成五个async函数,这五个函数之间是并行关系,而arr.forEachconsole.log("ss")是串行关系,因此该代码会首先输出ss,再同时输出1 2 3 4 5

而实际使用时,我们往往希望首先对数组进行遍历获取数据,然后对这些数据进行操作,具体到上个例子,即希望首先输出1 2 3 4 5,然后输出ss,其中数组遍历获取数据的代码可能为串行或并行,需要依据具体情境决定,而这时就无法使用forEach函数。

使用for...of...实现串行

async function test() {
    const arr = [1, 2, 3, 4, 5];
    for(const item of arr){
        const res = await new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(item);
          }, 2000);
        });
        console.log(res);
    }
    console.log("ss");
}

这时会依次间隔2s输出1 2 3 4 5,再输出ss

使用Promise.all实现并行

async function test() {
    const arr = [1, 2, 3, 4, 5];
    await Promise.all(
      arr.map(async (item) => {
        const res = await new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(item);
          }, 2000);
        });
        console.log(res);
      })
    );
    console.log("ss");
}

这时会间隔2s直接输出1 2 3 4 5,然后输出ss