Home > other >  How to handle promises when using (call, bind, apply) with JavaScript functions?
How to handle promises when using (call, bind, apply) with JavaScript functions?

Time:05-06

I have a function like so:

let maybeRun = function (cb: Function, allow: boolean, ctx: object = window) {
    return function () {
        if (!allow) return;

        cb.call(ctx, ...arguments);
        // cb.apply(ctx, arguments);
    };
};

In case cb is synchronous there is no problem, but how should I handle the case of cb returns a promise (asynchronous)?

let cb = async ()=> {...};

let foo = maybeRun(cb, true);

await foo()

I want the returned function foo to have same behaviour of cb (sync or async).

CodePudding user response:

You don't have to do anything special at all; an async function just returns a promise like any other return value.

But note that you're missing a return in your wrapper function. Your function was throwing away any return value it got (including a promise).

let maybeRun = function (cb: Function, allow: boolean, ctx: object = window) {
    return function () {
        if (!allow) return; // *** See note below

        return cb.call(ctx, ...arguments);
// −−−−−^^^^^^
    };
};

One wrinkle is that your wrapper now sometimes returns a promise and other times doesn't. There's nothing (standard) you can do to look at cb (without calling it) to see whether it returns a promise, so that may just be a limitation you have to deal with. (You can sniff out whether it's an async function, but you can't know if it's a non-async function that returns a promise.)


In a comment, you've said:

i didn't write a return because the wrapped functions i need this function for have no returns

That changes things for your specific use case: You'd just use await when calling the function:

let maybeRun = function (cb: Function, allow: boolean, ctx: object = window) {
    return async function () {
// −−−−−−−−^^^^^
        if (!allow) return;

        await cb.call(ctx, ...arguments);
// −−−−−^^^^^
    };
};

Now your function (being async) always returns a promise, and in the cases where cb returns a promise (either explicitly or because it's an async function), your function will wait for that promise to settle before returning, but won't return the fulfillment value.

Note that even with that change, cb is called synchronously when you call the wrapper function you got from maybeRun. An async function runs synchronously until the first time it has to wait for something. If cb is synchronous, it'll be run during that initial synchronous execution of the wrapper.

  • Related