如何在 Restify 中间件中捕获未经处理的承诺拒绝



我正在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 以允许正确的拒绝处理。

最新更新