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