如何等待 async.parallel?

Posted

技术标签:

【中文标题】如何等待 async.parallel?【英文标题】:How to await async.parallel? 【发布时间】:2021-08-07 08:32:01 【问题描述】:

假设我在下面有这个async.parallel 代码示例,用于并行运行异步函数并等待它们完成,然后再对结果运行代码。

async.parallel(
  one: async (callback) => /* ... some async code */ return someResult,
  two: async (callback) => /* ... some async code */ return someResult,
  three: async (callback) => /* ... some async code */ return someResult,
,(err,results) => 
  if (err)  /* … error handling code */ 
  /* … continued code */
  debug(results)      // prints "results" object successfully without problems
);

我想做的是将继续代码 (在传递给async.parallel的所有函数完成后继续/运行的代码)async.parallel之外。

我试过了:

const results = await async.parallel(
  one: async (callback) => /* ... some async code */ return someResult,
  two: async (callback) => /* ... some async code */ return someResult,
  three: async (callback) => /* ... some async code */ return someResult,
,(err,results) => 
  if (err)  /* … error handling code */ 
  debug("test print1: from inside async.parallel callback function");
        // called/printed after "test print2" meaning that async.parallel isn't awaited.
  return results;
);

/* … continued code */
debug("test print2: from outside async.parallel");
    // printed before "test print1" meaning that async.parallel isn't awaited.
debug(results)      // prints "undefined"

还有这个:

let results_outer;
await async.parallel(
  one: async (callback) => /* ... some async code */ return someResult,
  two: async (callback) => /* ... some async code */ return someResult,
  three: async (callback) => /* ... some async code */ return someResult,
,(err,results) => 
  if (err)  /* … error handling code */ 
  debug("test print1: from inside async.parallel callback function");
        // printed after "test print2" meaning that async.parallel isn't awaited.
  results_outer = results;
);

/* … continued code */
debug("test print2: from outside async.parallel");
    // printed before "test print1" meaning that async.parallel isn't awaited.
debug(results_outer)      // prints "undefined"

我的问题是,我怎样才能等待async.parallel 并成功获取结果对象?


建议的解决方案/替代方案: (目前还不是我的问题的解决方案,但它们可能是有用的临时替代方案)

备选方案 1: (我不喜欢,因为它看起来比 async.parallel 更丑/麻烦)

const results = await Promise.all([
  new Promise( (resolve, reject) => /* ... some async code */ resolve('some result 1') ),
  new Promise( (resolve, reject) => /* ... some async code */ resolve('some result 2') ),
  new Promise( (resolve, reject) => /* ... some async code */ resolve('some result 3') )
]);
debug(results);      // prints "results" object successfully without problems

关于备选方案 1 的说明: 为了使备选方案 1 更简单,我们可以创建 promisify(some_function):

const results = await Promise.all([
  promisfy(some_functionOne),
  promisfy(some_functionTwo),
  promisfy(some_functionThree)
]);
debug(results);      // prints "results" object successfully without problems

function promisfy(some_function) 
  const promise = new Promise( (resolve, reject) => 
    some_function_return_value = await some_function();
    resolve(some_function_return_value);
   );

  return promise;

进一步简化备选方案 1:

async_parallel([some_functionOne, some_functionTwo, some_functionThree]);
debug(results);      // prints "results" object successfully without problems

function async_parallel(functions_to_run) 
  let promises = functions_to_run.map(function_to_run => promisfy(function_to_run));
  const results = await Promise.all(promises);
  return results;

我们最终可能会构建一个类似于 异步库 的库并重新发明***,特别是当我们需要 concat、waterfall 等功能时。

【问题讨论】:

看看下面,这可能会有所帮助。 ***.com/questions/47794063/… 为什么不只是let results = await Promise.all([Car_model.findOne(...), Car_model.findOne(...). Car_model.findOne(...)]);?由于您的数据库已经支持承诺,我不明白为什么需要 async 库。 这些是猫鼬模型吗?你能用 promise API 代替异步吗? 自从 javascript 语言中 promise 和 async/await 的进步以及 nodejs 中支持 promise 的库和内置函数越来越多,使用像 async 这样的库的理由越来越少或Bluebird 更多。是的,仍然有一些情况,例如在执行大量并行操作时管理并发请求的数量,但大多数时候,您不再需要这些库,最好只使用现代工具进行编程Javascript 已经给你了。 不,最初的 async 库出现在 Promises 之前,旨在管理非 Promise、普通回调异步操作。此后它已被调整为合并 Promise,但它最初设计的大部分功能现在可以在没有它的情况下使用常规 Promise 的流控制来完成,特别是当您合并 async/await 时。 【参考方案1】:

由于您的数据库的现代版本已经支持 Promise,因此您不需要 async 库来执行此操作。相反,您可以这样做:

let results = await Promise.all([
     Car_model.findOne(...), 
     Car_model.findOne(...), 
     Car_model.findOne(...)
]);
console.log(results);

当然,此代码需要在 async 函数内,以便您可以使用 await

【讨论】:

【参考方案2】:

只要去掉回调函数,async.parallel 就会返回一个Promise

如果没有通过回调,async.parallel 返回一个承诺。

Source

const results = await async.parallel(
  one: async (callback) => /* ... some async code */ return someResult,
  two: async (callback) => /* ... some async code */ return someResult,
  three: async (callback) => /* ... some async code */ return someResult,
);
debug(results)      // prints "results" object successfully without problems

要处理错误,请将代码放入 try..catch:

try 
  let results = await async.parallel(
    one: async (callback) => /* ... some async code */ return someResult,
    two: async (callback) => /* ... some async code */ return someResult,
    three: async (callback) => /* ... some async code */ return someResult,
  );
  debug(results);
 catch(err) 
  /* … error handling code */

【讨论】:

我在线程上给出了相同的答案。 是的,它有点相似,但我不清楚如何使用await

以上是关于如何等待 async.parallel?的主要内容,如果未能解决你的问题,请参考以下文章

async.map 或 async.each 与 async.parallel 有啥区别?

async.map 或 async.each 与 async.parallel 有啥区别?

nodejs async.parallel 参数接收

使用 async.apply 时如何保持 this 的值? [复制]

很难理解节点中的 async.parallel

回调已被调用。但在那之前我从来没有打电话给回调。 async.parallel 中的错误? [复制]