JavaScript - 返回承诺和/或调用回调

JavaScript - Return promise AND/OR call callback?

本文关键字:调用 回调 返回 承诺 JavaScript      更新时间:2023-09-26

我经常在其他人的文档中看到类似的东西:

回调是可选的,如果省略则返回承诺。

这是我所拥有的:

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;
}

finish()函数只是避免了分散在周围的大量if...语句。

正在创建一个承诺对象,无论我是否使用它。

像这样测试:

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);
    }
});

这有效,但我想知道这是否是最好的方法,或者其他人是否有更好、更简洁的实现..?

如果您始终使用承诺,则可以简化此操作,无论如何您总是在创建承诺:

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;
}

你的函数总是基于承诺的,事实上它总是返回一个承诺。调用者可以自由地忽略这一点。回调参数只是使用该承诺的"遗留回退接口"(或"替代接口",如果您愿意)。

您可以通过始终返回一个 promise 来摆脱所有边缘情况,并定义一个默认回调(回调形状的标识函数)来处理无回调提供的情况:

const genericAsync = (stuff, callback = (e, i) => e || i) => new Promise(
  (resolve, reject) => doStuffWith(stuff, resolve, reject)
)
  .then(response => callback(null, response))
  .catch(callback);