javascript - 如何使用 promises 正确处理 express.js 中的错误(字符串或对象)

标签 javascript node.js express error-handling robustness

我不是在我的第一个 express.js 应用程序中,尽管我仍然需要找出处理错误的最可靠方法。

由于 io.js 是几个月前的现实,我使用原生 Promises 来帮助自己处理异步性,下面的代码反射(reflect)了这一点。

我的错误处理中间件如下:

router.use(function (err, req, res, next) {
  // in case err.custom is present, means is an "handled" Error, created by developers
  if (!!err.custom) {
    return res.status(err.code).json(err.message);
  }

  if (err instanceof Error) {
    console.error(err.stack);
    return res.status(500).send('Runtime Error'); // should be reported!
  }
  // last but not least, validation error
  res.status(400).send(err);
});

一个例子 Controller 是这样写的:

function callService1 (param1) {
  return new Promise(function (resolve, reject) {
    service.call(param1, function (err, data) {
      if (!!err) return reject(err); // this is an Error object?? not sure!

      if (!!data.handledError) { // this is an handled Error to the user, not 500
        return reject({ custom: true, status: 403, message: 'service1 tells you that myCoolParam is not valid' });
      }
      resolve(data);
    });
  };
}

function callService2 (dataFromParam1) {
  return new Promise(function (resolve, reject) {
    // something here
  });
}

// this is the API "controller"
module.exports = function (req, res, next) {
  callService1(req.body.myCoolParam)
  .then(callService2)
  .then(function (service2Output) {
    res.status(200).json({ message: 'everything went smooth!' });
  })
  .catch(next); // here is the catch-all errors
};

如您所见,express 中间件看起来非常整洁优雅。
我通常在 rejects() 中为用户处理所有有趣的错误,其中一些是使用我告诉错误处理中间件的对象调用的。

问题是示例中的 service 是第 3 方库。 这些库有时会返回一个字符串,有时会返回一个对象(来自外部 API),有时会返回一个 javascript 错误。

目前我无法处理自定义 javascript 对象,此外,如果我想向用户抛出错误 500,我必须执行 reject(new Error(err)); 但有时这个 err 是一个对象,导致:

Error: [object Object]
    at errorHandler (awesomeapi\postsomething.js:123:16)
    at IncomingMessage.<anonymous> (node_modules\mandrill-api\mandrill.js:83:24)
    at emitNone (events.js:72:20)
    at IncomingMessage.emit (events.js:163:7)
    at _stream_readable.js:891:16
    at process._tickCallback (node.js:337:11)

这一点都不酷,我真的很想找出一种优雅地处理这些错误的方法,而无需添加代码(如果可能的话),因为我发现这种语法非常优雅和简洁。

最佳答案

关于这个问题我想了很多,最后我创建/使用了这个 https://github.com/yzarubin/x-error/blob/master/lib/x-error.js它是一个自定义的服务器端错误对象,它继承了 Error,并扩展了处理 http 代码和响应的功能。

要将它应用于您的情况,我会做这样的事情:

function callService1 (param1) {
  return new Promise(function (resolve, reject) {
    service.call(param1, function (err, data) {
      if (!!err) return reject(new xError().extend(err).setHttpCode(500)); // This will inherit the original stack & message

      if (!!data.handledError) { 
        return reject(new xError('this is an handled Error to the user, not 500').setHttpCode(403));
      }
      resolve(data);
    });
  };
}

然后在您的 Controller 中,您可以检查 instanceof xError === true 并处理它,否则执行某种默认响应。但我也在一个应用程序中做了类似的事情,它确定每个 promise 最终都会解决或拒绝 xError 的实例:

router.use(function (err, req, res, next) {
  res.status(err.httpCode || 500).send(err.message || 'Internal error');
});

关于javascript - 如何使用 promises 正确处理 express.js 中的错误(字符串或对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28733325/

相关文章:

javascript - 获取 TypeError : Cannot call method 'releaseConnection' of null in mysql node. js

node.js - Node js 6 现在可以使用哪些 ES6?

javascript - Lodash 与 Mongoose 合并

html - 将单选按钮响应解析为数组 (Express.js)

node.js - Node JS : How to set template engine in krakenjs

javascript - router.get ('/' ) 在 expressjs 上不工作

c# - 将 JSON 对象反序列化为 C# 对象时整数列表的反序列化问题

javascript - 使用 Vue 3 将 SCSS 样式应用于全局 SCSS 文件中的 body 元素

javascript - 从选择选项中删除一些选项

javascript - 当下一条路线出现时,谷歌地图方向路线不会消失