1

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.

13
  • Look at below, this might help. stackoverflow.com/questions/47794063/… Commented May 18, 2021 at 5:46
  • 4
    Why not just let results = await Promise.all([Car_model.findOne(...), Car_model.findOne(...). Car_model.findOne(...)]);? Since your db already supports promises, I don't see why the async library is needed for this. Commented May 18, 2021 at 5:46
  • Are these mongoose models? Can you use the promise API instead of async? Commented May 18, 2021 at 5:49
  • 1
    Since the advance of promises and async/await in the Javascript language and more and more libraries and built-in functions in nodejs supporting promises, there are fewer and fewer reasons to use a library like async or Bluebird any more. Yes, there are still a few situations such as managing the number of concurrent requests when doing large numbers of parallel operations, but most of the time, you don't need those libraries any more and it's better to just program in the tools that modern Javascript already gives you. Commented May 18, 2021 at 8:03
  • 1
    No, the original async library came before Promises and was designed to manage non-promise, plain callback asynchronous operations. It has since been adapted to incorporate promises, but much of what it originally was designed to do can be done without it using the flow control of regular promises now, particularly when you incorporate async/await. Commented May 18, 2021 at 8:28

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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 */
}

2 Comments

I have given the same answer on the thread.
Yes it's somehow similar, however it wasn't clear for me how to use await with it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.