简体   繁体   中英

Conditionally call async function in Node

I have the following example code - the first part can result in an async call or not - either way it should continue. I cannot put the rest of the code within the async callback since it needs to run when condition is false. So how to do this?

if(condition) {
    someAsyncRequest(function(error, result)) {
        //do something then continue
    }
}

 //do this next whether condition is true or not

I assume that putting the code to come after in a function might be the way to go and call that function within the async call above or on an else call if condition is false - but is there an alternative way that doesn't require me breaking it up in functions?

A library I've used in Node quite often is Async ( https://github.com/caolan/async ). Last I checked this also has support for the browser so you should be able to npm / concat / minify this in your distribution. If you're using this on server-side only you should consider https://github.com/continuationlabs/insync , which is a slightly improved version of Async, with some of the browser support removed.

One of the common patterns I use when using conditional async calls is populate an array with the functions I want to use in order and pass that to async.waterfall.

I've included an example below.

var tasks = [];

if (conditionOne) {
    tasks.push(functionOne);
}

if (conditionTwo) {
    tasks.push(functionTwo);
}

if (conditionThree) {
   tasks.push(functionThree);
}

async.waterfall(tasks, function (err, result) {
    // do something with the result.
    // if any functions in the task throws an error, this function is 
    // immediately called with err == <that error>
});

var functionOne = function(callback) {
    // do something
    // callback(null, some_result);
};

var functionTwo = function(previousResult, callback) {
    // do something with previous result if needed
    // callback(null, previousResult, some_result);
};

var functionThree = function(previousResult, callback) {
    // do something with previous result if needed
    // callback(null, some_result);
};

Of course you could use promises instead. In either case I like to avoid nesting callbacks by using async or promises.

Some of the things you can avoid by NOT using nested callbacks are variable collision, hoisting bugs, "marching" to the right > > > >, hard to read code, etc.

Just declare some other function to be run whenever you need it :

var otherFunc = function() {
   //do this next whether condition is true or not
}

if(condition) {
    someAsyncRequest(function(error, result)) {
        //do something then continue

        otherFunc();
    }
} else {
    otherFunc();
}

Just an another way to do it, this is how I abstracted the pattern. There might be some libraries (promises?) that handle the same thing.

function conditional(condition, conditional_fun, callback) {
    if(condition)
        return conditional_fun(callback);
    return callback();
}

And then at the code you can write

conditional(something === undefined,
            function(callback) {
               fetch_that_something_async(function() {
                  callback();
               });
            },
            function() {

                       /// ... This is where your code would continue


             });

I would recommend using clojurescript which has an awesome core-async library which makes life super easy when dealing with async calls.

In your case, you would write something like this:

(go
  (when condition
    (<! (someAsyncRequest)))
  (otherCodeToHappenWhetherConditionIsTrueOrNot))

Note the go macro which will cause the body to run asynchronously, and the <! function which will block until the async function will return. Due to the <! function being inside the when condition, it will only block if the condition is true.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM