Marc B.
Marc B.

Reputation: 104

async.parallel doesn't wait for the parallel functions

Running the code bellow I just get "undefined". It seems like the async.parallel call executes the final function before the 4 parallel functions are finished.

function classify(filename) {
    var stack = [];

    var functionOne = async function(callback){
        //call to an API
        res = await classifierOne(filename);
        callback(null, res);
    }
    var functionTwo = async function(callback){
        //call to an API
        res = await classifierTwo(filename);
        callback(null, res);
    }
    var functionThree = async function(callback){
        //call to an API
        res = await classifierThree(filename);
        callback(null, res);
    }
    var functionFour = async function(callback){
        //call to an API
        res = await classifierFour(filename);
        callback(null, res);
    }

    stack.push(functionOne);
    stack.push(functionTwo);
    stack.push(functionThree);
    stack.push(functionFour);

    async.parallel(stack, function(err, res){
        console.log(res[0]);
    })
}

Upvotes: 0

Views: 1140

Answers (3)

hoangdv
hoangdv

Reputation: 16127

If you are using async with version 3.x, we have a big change - Support async/await , with the version, with tasks which have been wrap to a Promise (when you use async/await keyword) then the callback will be disable, you need to return value in the tasks instead of call callback(null, value).

This mean, to fix your case, the code will come to:

function classify(filename) {
    var stack = [];

    var functionOne = async function(){ // remove callback param
        //call to an API
        res = await classifierOne(filename);
        return res; // return value
    }
    var functionTwo = async function(){
        //call to an API
        res = await classifierTwo(filename);
        return res;
    }
    var functionThree = async function(){
        //call to an API
        res = await classifierThree(filename);
        return res;
    }
    var functionFour = async function(){
        //call to an API
        res = await classifierFour(filename);
        return res;
    }

    stack.push(functionOne);
    stack.push(functionTwo);
    stack.push(functionThree);
    stack.push(functionFour);

    async.parallel(stack, function(err, res){
        console.log(res[0]);
    })
}

P/s: My suggestion is using Promise.all for this case. Say no to callback.

async function classify(filename) { // Make this function become a async function
    var stack = [];

    var functionOne = async function(){ // remove callback param
        //call to an API
        res = await classifierOne(filename);
        return res; // return value
    }
    var functionTwo = async function(){
        //call to an API
        res = await classifierTwo(filename);
        return res;
    }
    var functionThree = async function(){
        //call to an API
        res = await classifierThree(filename);
        return res;
    }
    var functionFour = async function(){
        //call to an API
        res = await classifierFour(filename);
        return res;
    }

    stack.push(functionOne);
    stack.push(functionTwo);
    stack.push(functionThree);
    stack.push(functionFour);

    const result = await Promise.all(stack); // Wait until all "task" finish
    console.log(result);
    return result; // Return the result of all tasks
}

// Call classify function inner a async function
const result = await classify('your_file_name'); // await keyword
console.log(result);

Upvotes: 2

Stan Wiechers
Stan Wiechers

Reputation: 2092

Your methods like i.e. functionOne missed the return and didn't a callback. The below returns ["1","2","3","4"].

const async = require('async');

const classifierOne   = async ()=> "1"
const classifierTwo   = async ()=> "2"
const classifierThree = async ()=> "3"
const classifierFour  = async ()=> "4"

const classify = filename => {
    var stack = [];

    var functionOne   = async ()=> classifierOne(filename);
    var functionTwo   = async ()=> classifierTwo(filename);
    var functionThree = async ()=> classifierThree(filename);
    var functionFour  = async ()=> classifierFour(filename);


    stack.push(functionOne);
    stack.push(functionTwo);
    stack.push(functionThree);
    stack.push(functionFour);

    async.parallel(stack, (err, res)=>{
        console.log(res);
    })
}

classify("x");

Upvotes: 0

Ashish Modi
Ashish Modi

Reputation: 7770

I am not too sure about the async npm library but on top of it looks like it doesn't work when you have a callback function as async. If you try it using native promises, it will work. Something like

function classify(filename) {
  var stack = [];

  var functionOne = function(callback) {
    //call to an API
    classifierOne(filename).then(res => callback(null, res));
  };
  var functionTwo = function(callback) {
    classifierTwo(filename).then(res => callback(null, res));
  };
  var functionThree = function(callback) {
    classifierThree(filename).then(res => callback(null, res));
  };
  var functionFour = function(callback) {
    classifierFour(filename).then(res => callback(null, res));
  };

  stack.push(functionOne);
  stack.push(functionTwo);
  stack.push(functionThree);
  stack.push(functionFour);
  async.parallel(stack, function(err, res) {
    console.log(res);
  });
}

Upvotes: 0

Related Questions