0

I need to wait for tasks of two API callback functions and when tasks are done I would like to receive a callback so I can use data from both functions.

I would like the function will be parallel executed ... I read a lot of questions about async.parallel but I can't find a way to use these functions with async.

Of course async is only an example, any other way will be fine if it works.

I'm sorry for my bad english, I hope the code is easier to understand.

Thank you

var dataFunctionA = "";
var dataFunctionB = "";

var callbackFunctionA = function(err, response, data) {
  // do some work with data
  dataFunctionA = "Hello";
}

var callbackFunctionB = function(err, response, data) {
  // do some work with data
  dataFunctionB = " World!";
}

function printHelloWorld(){
   console.write(dataFunctionA + dataFunctionB);
}


APIClient.functionA(paramA, callbackFunctionA);

APIClient.functionB(paramB, callbackFunctionB);

// need to wait for the two callbacks
printHelloWorld();

2 Answers 2

1

If you don't want to use promises you could do something like:

var dataFunctionA = "";
var dataFunctionB = "";
var dataFunctionCount = 2;

function checkDone() {
  dataFunctionCount--;
  if(dataFunctionCount === 0) {
// need to wait for the two callbacks
printHelloWorld();  
  }
}

var callbackFunctionA = function(err, response, data) {
  // do some work with data
  dataFunctionA = "Hello";
  checkDone();
}

var callbackFunctionB = function(err, response, data) {
  // do some work with data
  dataFunctionB = " World!";
  checkDone();
}

function printHelloWorld(){
   console.write(dataFunctionA + dataFunctionB);
}

APIClient.functionA(paramA, callbackFunctionA);

APIClient.functionB(paramB, callbackFunctionB);

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

3 Comments

It works like a charm,thank you. I just added dataFunctionCount = 2; after printHelloWorld(); so checkDone() is ready to be reused ( I need to call those two API functions many times ). Would you please show me the same example using promises ?
this solution does not scale well and not very clean. What if you have 10, 100 functions you want to execute. will you create 100 variables to hold the data values for them ? i would either go with promises or async as i have shown below
A scalable solution using promises was given by @AhmadAssaf. Sometimes people want a quick and dirty solution without all the overhead and other times they want industrial strength.
0

Using the async.parallel you can achieve that by doing:

async.parallel({
    functionA: APIClient.functionA.bind(null, paramA),
    functionB: APIClient.functionB.bind(null, paramB)

}, function(error, results) {
    processCallbacks(error, results);
});

And in your functions, after finishing data processing you should call the implicit parallel callback passed.

functionA(paramA, callback) {
   // data processing
   callback(null, resultFromProcessingParamA);
}

What you do here is passing an object of functions to the parallel. The key of the object here is used so that you can access the results array. For the example above, the result of functionA will be saved in results.functionA and so on.

The first parameter is null (due to .bind) and then you pass all the other needed params. The callback is passed automatically by the parallel between functions and the last callback is only called when all the functions finish.

Please run the following snippet to understand better.

function functionA (paramA, callback) {
  $('body').append('<p> Parallel execution of function A and waiting for 5 seconds, parameter passed: ' + paramA + '</p>');
  setTimeout(function(){
        $('body').append('<p>processed functionA</p>');
    callback(null, ++paramA);
  }, 5000);
}

function functionB (paramB, callback) {
  $('body').append('<p> Parallel execution of function B and waiting for 1 second, parameter passed: ' + paramB + '</p>');
  setTimeout(function(){
    $('body').append('<p>processed functionB</p>');
    callback(null, ++paramB);
  }, 1000);
}

function processCallbacks (results) {
  $('body').append('<p> Processing results from two functions. ParamA now is:' + results.functionA + ' and paramB now is:' + results.functionB + '</p>');
}


async.parallel({
  
    functionA: functionA.bind(null, 10),
    functionB: functionB.bind(null, 2)

}, function(error, results) {
  console.log(results);
    if (!error) {
      processCallbacks(results);
    }
  
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/async/1.5.0/async.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

7 Comments

I get 'throw "Must supply a callback"' on the API call ... any idea ? thanks
because on your functions you must throw a callback .. i am editing the answer now. Check it
I'm doing some tests with your example ... the snippet is very good to help me understand the async.parallel. What I can't understand is why I should modify the API call :( I can't and I don't want to modify it. It's an npm module and it will be upgraded so I don't want to edit it. I think I should use it as provided from the authors. Maybe I'm making a mess ...
@NiuB-Daniele in my example i am not using the API call because i don't include the API in the snippet. When you have this in your code you will be able to use the API calls :)
unfortunately not ... I can't use the API calls in this way, I tried in many ways and I always receive an error :(
|

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.