Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript - Return promise AND/OR call callback?

I often see in other peoples docs something like:

Callback is optional, if omitted returns a promise.

This is what I have:

export function doSomeAsync(options, callback) {

    const useCallback = (callback && typeof callback == 'function');

    const promise = new Promise((resolve, reject) => {

        // --- do async stuff here ---
        const check = (options.num === 1) ? true : false;
        setTimeout(() => {
            if (check) {
                finish(true, "Number is 1");
            } else {
                finish(false, new Error("Number is not 1"));
            }
        }, 1000);
        // ---------------------------

        function finish(ok, rtn) {
            if (useCallback) {
                if (ok) {
                    callback(null, rtn);
                } else {
                    callback(rtn, null);
                }
            } else {
                if (ok) {
                    resolve(rtn);
                } else {
                    reject(rtn);
                }
            }
        }

    });

    return (useCallback) ? false : promise;
}

The finish() function just avoids lots of if... statements scattered around.

I'm creating a promise object, whether or not I use it.

Testing like this:

doSomeAsync({ num: 1 }).then((result) => {
    console.log('p result', result);
}).catch((err) => {
    console.log('p err', err);
});

doSomeAsync({ num: 1 }, (err, result) => {
    if (err) {
        console.log('cb err', err);
    } else {
        console.log('cb result', result);
    }
});

This works, but I'm wondering if this is the best way, or if others have a better and more succinct implementation..?

like image 451
Stephen Last Avatar asked Apr 25 '16 10:04

Stephen Last


1 Answers

This could be simplified if you simply always used the promise, which you're always creating anyway:

export function doSomeAsync(options, callback) {
    const promise = new Promise((resolve, reject) => {
        const check = (options.num === 1) ? true : false;
        setTimeout(() => {
            if (check) {
                resolve("Number is 1");
            } else {
                reject(new Error("Number is not 1"));
            }
        }, 1000);
    });

    if (callback && typeof callback == 'function') {
        promise.then(callback.bind(null, null), callback);
    }

    return promise;
}

Your function is always promise-based, also in the fact that it always returns a promise. The caller is simply free to ignore that. The callback argument is merely a "legacy fallback interface" (or "alternative interface" if you prefer) to using that promise.

like image 92
deceze Avatar answered Nov 16 '22 04:11

deceze