Suhail Gupta
Suhail Gupta

Reputation: 23276

Run three functions asynchronously and wait till the three functions get completed

In the following function named start three functions are called successively. After all the functions are executed, the container function start is called again.

Is there any way, where I could run the three functions parallelly or asynchronously and when all the three get completed, the start method is called again.

function start(){
    resolveErrorQueue((err,data)=>{
            if(err)
                console.log(err);
            else{
                checkIfAlive((err,data) => {
                   if(err)
                       console.log(err);
                   else{
                      prepareServer((err,data) => {
                        if(err)
                            console.log(err);
                        else
                            start();
                      }); 
                   }                    
                });
            }               
    });
}

Upvotes: 1

Views: 349

Answers (5)

Shubham Verma
Shubham Verma

Reputation: 9933

You can use async.series() method in nodejs. The async is a module which provide various method to execute asynchoronous method in nodejs.

For example:

async.series([function1,function2,function3],function(err,result{
if(err){
      // do here if error occured. 
  }
      console.log(result);
     // DO here what you want to do after function1, function2 and function3 completion. 
});


var function1 = function(cb){
     // do here in function1 
        cb(null,'ok');
  };

var function2 = function(cb){
    // do here in function2 
        cb(null,'ok');
  };

var function3 = function(cb){
   // do here in function3 
        cb(null,'ok');
  };

You can add any number of function as an arguments in async.series().

Upvotes: 0

Perspectivus
Perspectivus

Reputation: 990

I agree with user2263572's answer that you should use promises. It's even simpler using ES6 Promises that have been supported natively by Node.js since v4.7.1.

Here's a working example:

function resolveErrorQueue(resolve, reject) {
    setTimeout(() => {
        resolve("no errors in queue");
    }, 1000);
}

function checkIfAlive(resolve, reject) {
    setTimeout(() => {
        resolve("server is alive");
    }, 999);
};

function prepareServer(resolve, reject) {
    setTimeout(() => {
        resolve("server is prepared");
    }, 1001);
};

var counter = 0;
function start() {
    Promise.all([new Promise(resolveErrorQueue), new Promise(checkIfAlive), new Promise(prepareServer)]).then(values => {
        console.log(`${++counter}: ${values}`);
        start();
    });
}
start();

Upvotes: 1

Sangharsh
Sangharsh

Reputation: 3019

Using async module's parallel:

async.parallel([resolveErrorQueue, checkIfAlive, prepareServer], (err, results) => {
  if (err)
    console.error(err);
  else
    start();
});

Since your methods seems to work with callback async module will fit well. If methods also support promises then that can also be done, e.g. using Bluebird Promise.join or Q.all (as mentioned by @user2263572).

Upvotes: 1

njlarsson
njlarsson

Reputation: 2340

Not entirely sure what you are after, but something like this, perhaps?

function start(){
    var leftToRun = 3;

    resolveErrorQueue((err,data)=>{
        if(err)
            console.log(err);
        else{
            if (--leftToRun === 0) { start(); }
        }
    });

    checkIfAlive((err,data) => {
        if(err)
            console.log(err);
        else{
            if (--leftToRun === 0) { start(); }
        }
    });

    prepareServer((err,data) => {
        if(err)
            console.log(err);
        else
            if (--leftToRun === 0) { start(); }
    }); 
}

It won't actually run in parallell, since Node only runs your code in one thread, but if the operations you call are asynchronous, the functions don't have to finish in order.

Upvotes: 0

user2263572
user2263572

Reputation: 5606

The cleanest way is using a promise library. For example, in Q you can use the q.all function

Q.all([getFromDisk(), getFromCloud()]).done(function (values) {
    assert(values[0] === values[1]); // values[0] is fromDisk and values[1] is fromCloud
});

If you want to do it without promises, you can create a global variable that is incremented each time an async function completes. Then call your 3 async functions, and in the callback increment the global variable. You can also store the return data globally if needed.

You can then use a while loop or setInterval to check if the 3 functions have all returned.

Upvotes: 1

Related Questions