我正在Node.js上编写一个Restify应用程序。我需要有一个函数,当 Restify 回调中发生一些错误时调用该函数。此函数应向客户端发送响应。如果我不使用承诺或异步函数,我可以做这样的事情:
server.on('uncaughtException', (req, res, route, err) => {
log.error(err);
res.send(err);
});
但是,如果我的回调是函数async
,则不会调用函数内的异常,而是引发unhandledPromiseRejection
。
如何重构我的代码,使其像处理常见错误一样处理未处理的 Promise 拒绝?
是的,我知道我可以检查 Restify 中间件本身内部的错误,但它仍然使代码更复杂,编写起来更容易
if (!core.validateUUID(req.params.deviceId)) {
throw new Error(`Device ${req.params.deviceId} is wrong`)
}
然后
if (!core.validateUUID(req.params.deviceId)) {
return next(new restify.InvalidArgumentError({ body: {
success: false,
error: `Device ${req.params.deviceId} is wrong`,
} }));
}
我为此苦苦挣扎了一段时间,我想出了一个简单的解决方案。我创建了一个简单的包装函数,它包装路由处理程序/中间件并在 promise 中运行代码。这样,可以处理未处理的拒绝和未捕获的异常是相同的回调:
// your error general handler
function errorResponse(req, res, err) { ... }
/**
* When using promises inside handler, you need to return the Promise from it to allow proper rejection handling
*
* @param {Function} callback with `req`, `res` and `next` parameters
* @returns {Function}
*/
function catcher(callback) {
return (req, res, next) => {
Promise
.resolve()
.then(() => callback(req, res, next))
.catch(err => errorResponse(req, res, err));
};
}
// use it like this
server.use(catcher(middleware1));
server.post(catcher(postRoute));
server.get(catcher(getRoute));
在处理程序中使用 promise 时,需要从中返回 Promise 以允许正确的拒绝处理。