Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle an async function that depends on multiple other async functions

I have an asynchronous function that works with the result of two other async functions.

Till now what I was doing is that I write function2 in the callback function1 and function2 in the callback of function2

function1(callbackFunction() {
    function2(callbackFunction() {
        function3()
    })
})

Is there any other way to handle this. I work usually with JavaScript code in client side and in nodeJs.

My scenario is that for function2 I don't need output from function1. In another words function1 and function2 are independent; but function3 is dependent on function1 and function2.

I want my function2 to run independent on function1 but function3 to run dependent on both functio1 and function2.

Is there anything like

function1();
function2();
when(funtion1.complete && funtion2.complete) {
    function3();
}
like image 944
Okky Avatar asked May 20 '14 02:05

Okky


People also ask

How do I run multiple async functions at once?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).

Do async functions run in parallel?

Asynchronous operations in parallelThe method async. parallel() is used to run multiple asynchronous operations in parallel. The first argument to async. parallel() is a collection of the asynchronous functions to run (an array, object or other iterable).

Can async function have more than one await?

Using one try/catch block containing multiple await operations is fine. The await operator stores its parent async functions' execution context and returns to the event loop. Execution of the await operator resumes when it is called back with the settled state and value of its operand.

Do async functions run on another thread?

No, it does not. It MAY start another thread internally and return that task, but the general idea is that it does not run on any thread.


2 Answers

There are some good libraries to deal with orchestrating asynchronous functions. async and q (or other Promises/A libraries) help.

If function2 does not depend on the result of function1, you can execute them in parallel. Here's how it looks using async (these examples assume that your callback has a function(err, result) signature, which is the defacto pattern for Node:

async.parallel([
    function(callback) { function1(callback); },
    function(callback) { function2(callback); }
], function(err, values) {
    function3(values[0], values[1]);
});

If function2 depends on the result from function1, waterfall may be a better pattern:

async.waterfall([
    function(callback) { function1(callback); },
    function(result, callback) { function2(result, callback); },
    function(result, callback) { function3(result, callback); },
]);

Personally, I like q, because you can pass promises around and do all kinds of nifty stuff. Here's how this would look using that:

q.nfcall(function1)
  .then(function(result) { return q.nfcall(function2); })
  .then(function(result) { return q.nfcall(function3); })
  .fail(function(err) {
      // If any of them fail, this is called.
  });

Or if function1 and function2 can be done in arbitrary order:

q.all([q.nfcall(function1), q.nfcall(function2)])
 .then(function(values) { function3(values[0], values[1]); })
 .fail(function(err) {
 });
like image 117
Jacob Avatar answered Oct 12 '22 20:10

Jacob


Here is a solution that I baked. You can try a call manager to call the dependant functions

var func1 = function() {
    console.log("Dependant call ... " + 1);
};
var func2 = function() {
    console.log("Dependant call ... " + 2);
};
var func3 = function() {
    console.log("Dependant call ... " + 3);
};
var func4 = function() {
    console.log("Dependant call ... " + 4);
};


var CallManager = function(funcs_config) {
    var _this = this;

    _this.functions = funcs_config;
    _this.callAsynchronous = function(f) {
        if (f != undefined) {
            for (var i = 0; i < f.length; i++) {
                f[i].call(function() {
                    this.callAsynchronous(f.splice(0,1));
                });
            }
            return;
        }

        for (var func in _this.functions) {
            if (_this.functions[func].length == 0) {
                //not dependent to any function
            } else {
                console.log('Calling....' + func);
                _this.callAsynchronous(_this.functions[func]);
                eval(func +'();');
            }
        }
    };

    return _this;
};


var callManager = new CallManager({
    //dependency configuration
    func2: [func1], //func2 depends on func1
    func3: [func2],
    func4: [func1, func3] //func4 depends on both func1 and func3
});

callManager.callAsynchronous();

With the current config provided above, when it is run the output is given as -

Calling....func2
Dependant call ... 1
Dependant call ... 2
Calling....func3
Dependant call ... 2
Dependant call ... 3
Calling....func4
Dependant call ... 1
Dependant call ... 3
Dependant call ... 4
like image 27
brainless coder Avatar answered Oct 12 '22 21:10

brainless coder