简体   繁体   中英

How to await async.parallel?

Let's say I have this async.parallel code example below, to run async functions in parallel and wait for them to complete before running code on results.

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
});

What I want to do is to put continued code (code to continue/run after all functions passed to async.parallel are completed) outside async.parallel .

I tried this:

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"

And this:

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"

My question is, How can I await async.parallel and get results object successfuly?


Suggested Solutions/Alternatives: (Non is yet a solution for my question, however they may be useful temporary alternatives)

Alternative 1: (I don't prefer because it seems uglier/cumbersome than 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

Note on Alternative 1:
To make Alternative 1 simpler, we can create 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;
}

To simplify Alternative 1 further:

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;
}

We may end up building a similar library to async library and reinvent the wheel, specially when we need features like concat , waterfall , etc.

Since a modern version of your database already supports promises, you don't need the async library to do this. You can, instead, just do this:

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

This code would, of course, need to be inside an async function so you can use await .

Just remove the callback function, and async.parallel will return a Promise .

async.parallel returns a promise, if a callback is not passed.

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

and to handle errors, put code within a 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 */
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM