如何重构使用相同函数但在调用函数中还包含变量的 promise catch?

How to refactor a promise catch that uses the same function, but also a variable in the calling one?

我使用 ExpressJS for routing, and bluebird 作为 Promise。 我对几条路线重复了以下代码,最后它们都具有相同的 .catch 函数,并以 json 失败响应。

router.get('/', function(req, res) {
    return somePromise
    .then(function doesSomething(someVariable) {
        doSomething;
    })
    .catch(function catchesError(err) {
        return res.json({ success: false });
    });
});

我想提取 catchesError 函数,但是它无法使用 res 对象。

有什么建议吗?

只需创建一个函数并将 res 对象作为参数传递,将 return 作为函数传递。

function makeErrorCatcher(res) {
    return function catchesError(err) {
        return res.json({
            success: false
        });
    }
}
router.get('/', function (req, res) {
    return somePromise
        .then(function doesSomething(someVariable) {
            doSomething;
        })
        .catch(makeErrorCatcher(res));
});

您可以修饰 .get 以传递一个默认的捕获处理程序。 (假设您对自定义路由器不感兴趣):

Object.keys(router).forEach(function(key){ // for each method
    router[key+"P"] = function(path, fn){ // create a decorated alt
        router[key].call(router, function(req, res, next){  // delegate
            var that = this, args = arguments;
            return Promise.try(function(){ // wrap to make throw safe
                return fn.apply(that, args); // delegation
            }).catch(function catchesError(err){
                // LOG YOUR ERRORS, DON'T CATCH ALL
                return res.json({ success: false });
            });
        });
    };
});

这会让你做:

router.getP('/', function(req, res) {
    return somePromise.then(function doesSomething(someVariable) {
        doSomething;
    });
});

现在将自动捕获错误并发送适当的 JSON。消除重复或完全忘记错误的可能性。

与 Ben Fortune 的解决方案非常相似,使用 bind()

function catchesError(res, err) {
    return res.json({ success: false });
}

router.get('/', function(req, res) {
    return somePromise
    .then(function doesSomething(someVariable) {
        doSomething;
    })
    .catch(catchesError.bind(null, res));
});

如果您在 class.

中,请将 null 替换为 this

如果您不打算使用承诺链,您可以添加一个附加 catch 处理程序的 catcher 函数:

function catcher(promise, req, res) {
    promise.catch(function catchesError(err) {
        return res.json({ success: false });
    });
    return promise;
}

router.get('/', function(req, res) {
    return catcher(somePromise, req, res)
    .then(function doesSomething(someVariable) {
        doSomething;
    });
});

但是,如果您想使用出色的承诺链机制,则需要手动调用 catch 处理程序以确保它是链中的最后一个:

function makeCatchHandler(res) {
    return function(err) {
        return res.json({ success: false });
    };
}

router.get('/', function(req, res) {
    return catcher(somePromise, req, res)
    .then(function doesSomething(someVariable) {
        doSomething;
    }).catch(makeCatchHandler(res));
});