NodeJS Promise.all在等待所有组件完成之后再继续

时间:2018-07-20 07:38:17

标签: javascript node.js promise async-await

我正在尝试处理由对象组成的数组。每个对象都有一个字段,其值是数字数组。我想以异步/等待方式处理所有数字数组的所有组件。

数据示例如下:

const data = [{
  numbers: [1, 2, 3],
}, {
  numbers: [4, 5, 6],
}, {
  numbers: [7, 8, 9],
}];

我已经通过两种方式实现了此功能。第一个代码是这样的:

const processData1 = async(data) => {
  return Promise.all(data.map(async(d) => {
    const partial = await Promise.all(d.numbers.map(async(n) => {
      console.log('INIT', n);
      const number = await processNumber(n);
      console.log('END', n);
      return number;
    }));
    return partial;
  }));
};

第二个是这个

const processData2 = async(data) => {
  for (const d of data) {
    for (let n of d.numbers) {
      console.log('INIT', n);
      n = await processNumber(n);
      console.log('END', n);
    }
  }
};

在所有情况下,我期望控制台中打印的都是“ INIT”和“ END”,顺序正确。在第二个代码函数中也是如此。但是在第一个中,我看到的INIT和数字一样多,然后所有对应的END:

**** processData1 ****
INIT 1
INIT 2
INIT 3
INIT 4
INIT 5
INIT 6
INIT 7
INIT 8
INIT 9
END 1
END 2
END 3
END 4
END 5
END 6
END 7
END 8
END 9
**** processData2 ****
INIT 1
END 1
INIT 2
END 2
INIT 3
END 3
INIT 4
END 4
INIT 5
END 5
INIT 6
END 6
INIT 7
END 7
INIT 8
END 8
INIT 9
END 9

这怎么可能? await processNumber为什么要等待所有数字都被解析?

2 个答案:

答案 0 :(得分:3)

在第一个示例中,您仅等待Promise.all的结果,这意味着每个诺言将同时执行。在第二个示例中,您等待每个单独的诺言,这些诺言迫使他们依次执行。

这两种情况都有其用途,第一种情况最好,如果您不关心顺序,即操作可以并发运行,第二种情况对于强制异步代码按顺序执行很有用。

答案 1 :(得分:1)

来自MDN

  

Promise.all(iterable)方法返回一个Promise   当可迭代参数中的所有promise具有时解析   解决或可迭代参数不包含任何承诺时。它   拒绝的原因是第一个拒绝的承诺。

这意味着所有传递的诺言都将并行执行,并且只有在所有诺言结束时才会完成和解决。在您的示例中,子承诺被授予按顺序启动。在您的情况下,它们碰巧以相同的顺序结束,但这不一定能保证(一个可能比另一个花费更长的时间,然后再结束)。

对于第二个示例,您要做的就是启动并立即等待for循环中的每个processNumber(n),导致每个进程依次开始和结束。