如何重构使用相同函数的 promise catch,但也使用调用函数中的变量



我用 ExpressJS 做路由,用 bluebird 做 Promises。我有以下代码重复了几个路由,最后它们都具有相同的 .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对象作为参数传递并返回一个函数。

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以具有默认的 catch 处理程序。(假设您对自定义路由器不感兴趣):

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

如果您在类中,请将 null 替换为 this

如果您不打算使用 promise chainging,则可以添加一个附加 catch handler 的 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));
});

最新更新