Search code examples
javascriptasynchronouspromiseconditional-statementsecmascript-5

How to call asynchronous function conditionally in JavaScript


I would like to make a conditional asynchronous function call in JavaScript/ES5.

Say I have a module myService with a function myAsyncFunction, which is doing some logic inside and returns result with a callback like the following:

myService.myAsyncFunction(param1, param2, (error, success) => {
    if (error) {
        // handle error
        return;
    }
    // handle success
});

But in certain conditions, I would like it to directly fall into the "handle success" without running the logic inside myService.myAsyncFunction, which may take some time and resources.

The most straightforward way that I imagine is to create a dummy function which imitates myService.myAsyncFunction and calls the callback with no error like the following:

var myGenericFunction;

if ( /* I would like to skip unnecessary logic */) {
    myGenericFunction = function (param1, param2, callback) {
        callback(null);
    }
} else {
    myGenericFunction = myService.myAsyncFunction;
}

myGenericFunction(param1, param2, (error, success) => {
    if (error) {
        // handle error
        return;
    }
    // handle success
});

This is what I have ended up with but I guess there should be a better way in terms of both syntax and performance. Do you have any suggestion for it?

Note: Promise.resolve on ES6 can propose a solution to directly fall into success case but I wonder what would be ES5 solution.


Solution

  • First, it's super easy to pull in a Promise polyfill for javascript environments that don't support it. It should work all the way back to Ecmascript 3.

    Ignoring that, if you have an async function such as this:

    function myAsync(arg1, callback) {
    
    }
    

    But for some value or arg1 you want to immediately call the callback, but you can't change the function, the reasonable way to do this, is indeed to just wrap it:

    function myAsyncWrapped(arg1, callback) {
       if (arg1 === SOME_VALUES) {
         callback(null, true);
       } else {
         myAsync(arg1, callback);
       }
    }
    

    If you need to do this for many async functions, it could be generalized as:

    function asyncWrapper(innerFunction) {
       return (arg1, callback) {
         if (arg1 === SOME_VALUES) {
           callback(null, true);
         } else {
           innerFunction(arg1, callback);
         }
       }
    }
    

    so you can call this as:

    myAsyncWrapped = asyncWrapper(myAsync);