4

Suppose I use Node.js to try to run two async calls to get some answers. I know there's an async package, where you can just pass two functions, and an optional callback.

async.parallel([fun1(){callback(null,1);},
fun2(){callback(null,2);}],
function(err, results) {  
});

But suppose I have a priority now, if fun1 returns a value, then I do not need fun2's answer, only if fun1 returns null, then I wait for fun2. So I don't want to use the callback function, because the callback waits for both functions to finish, and fun2 may take very long.

Right now I just use a very exhaustive way by creating a callback function for both async calls.

function(){
    var theAnswer,FromFun1,FromFun2;
    var reply1,reply2;
    fun1(reply1="answered";FromFun1=1;complete());
    fun2(reply2="answered";FromFun2=2;complete());
   function complete(answer){
      if(reply1=="answered"){
           theAnswer=FromFun1;
      }else if(reply1==null){
           // Don't do anything because fun1 is not finished running. 
       }else if(reply2=="answered"){
           theAnswer=FromFun2;
       }else{
           // Both have no answer, err.
       }
   }
}

Is there a better way to do this?

NobodyNada
  • 7,529
  • 6
  • 44
  • 51
Evilsanta
  • 1,032
  • 11
  • 18
  • 1
    You should try promises instead. It would be as simple as `var second = fun2(); return fun1().then(function(r) { return r || second; })` – Bergi Jul 21 '14 at 20:05
  • Thanks Bergi, that was helpful. I would vote you up :) – Evilsanta Jul 22 '14 at 04:27
  • Thanks @Bergi, that was helpful. I would vote you up :). I have one more question tho. In the then(), it either return r, which is the answer, or 'second', which is a promise. How do I handle that next? – Evilsanta Jul 22 '14 at 05:09
  • If you return the answer, it will use that, if you return a promise from `then`, it will wait for that. That's the point of `then` :-) – Bergi Jul 22 '14 at 11:25

2 Answers2

2

Its better to use waterfall instead of parallel execution coz you can pass the result form your previous function to next one as argument.

async.waterfall([
function(callback){
    callback(null, 'one');
},
function(arg1, callback){

    // arg1 now equals 'one'
   if(arg1==null){
   // it will not take time it returns immediately 
    callback(null, 'done');

    }else{
    // do your another stuff here fun2 logic here 
    // it will not be executed and so it dont take time 
      }
  }
  ], function (err, result) {
  // result now equals 'done'    
}); 
Vivek Bajpai
  • 1,617
  • 1
  • 19
  • 35
  • Does that mean the functions in waterfall are sequential? – Evilsanta Jul 21 '14 at 19:00
  • yes they are sequential but they dont took much time – Vivek Bajpai Jul 21 '14 at 19:19
  • 2
    The OP has the benefit of running both functions in parallel; this should benefit should be used. Waterfall happens in series, so while this is an elegant solution, is not fully optimal. – zamnuts Jul 21 '14 at 19:35
  • @zamnuts i know its not the optimal solution but as stated by OP the execution of second function depends on the output of first one so i dont think that can be done parallel. – Vivek Bajpai Jul 21 '14 at 19:40
  • @VivekBajpai it could if after either of the functions return a valid result it can cancel/abort the remaining pending function, but that depends on what is happening internally (e.g. something with socket). – zamnuts Jul 21 '14 at 19:44
  • I think OP need to check the func1 output first and then he goto the second one so when he calls the second function with a null argument it returns straight – Vivek Bajpai Jul 21 '14 at 19:53
2

The trick I've used for this scenario is to return "done" in first argument of the callback:

async.parallel([
  function(callback){
    callback("done",1);
  },
  function(callback){
    callback(null,2);
  }
], function(err, results) { 
  console.log(err, results);   // done [ 1 ] or done [ 1 , 2 ] 
});

Sounds like a hack and I don't usually do it but in some rare cases like this one, it actually keeps the code clean... just document it so that others know what you intention is.

Ben
  • 5,024
  • 2
  • 18
  • 23
  • Using exceptions for control flow, especially to short-cut async functions, is a clever hack :-) – Bergi Jul 21 '14 at 23:05