如何处理Express异常?

简介: 译者按:根据墨菲定律:“有可能出错的事情,就会出错”。那么,既然代码必然会出错,我们就应该处理好异常。原文: How to handle errors in Express译者:Fundebug为了保证可读性,本文采用意译而非直译。

译者按:根据墨菲定律:“有可能出错的事情,就会出错”。那么,既然代码必然会出错,我们就应该处理好异常。

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

处理异常是编程非常重要的一点。我们的程序依赖于第三方服务、数据库以及我们的用户,一切都不可预料。数据库可能会宕机,第三方服务可能会崩溃,用户可能会使用错误的参数调用我们的接口。

为了处理各种复杂的情况,我们必须处理好代码异常,下面是代码示例:

app.get('/users/:id', (req, res) => {
  const userId = req.params.id
  if (!userId) {
    return res.sendStatus(400).json({
      error: 'Missing id'
    })
  }

  Users.get(userId, (err, user) => {
    if (err) {
      return res.sendStatus(500).json(err)
    }

    res.send(users)
  })
})

代码中处理了异常,但是存在问题:

  • 在多处代码处理异常
  • 没有使用Express的异常处理模块来统一处理异常

接下来,我们来一步步优化代码异常处理。

Express异常处理中间件

所有Express的路由处理函数都有第三个参数next,它可以用来调用下一个中间件,也可以将错误传递给错误处理中间件:

app.get('/users/:id', (req, res, next) => {
  const userId = req.params.id
  if (!userId) {
    const error = new Error('missing id')
    error.httpStatusCode = 400
    return next(error)
  }

  Users.get(userId, (err, user) => {
    if (err) {
      err.httpStatusCode = 500
      return next(err)
    }

    res.send(users)
  })
})

使用next(err),Express就知道出错了,并把这个错误传递给错误处理模块。为了处理这些错误,需要添加一个中间件,它有4个参数:

app.use((err, req, res, next) => {
  // log the error...
  res.sendStatus(err.httpStatusCode).json(err)
})

这样,我们就可以使用中间件统一处理错误了。但是,现在的代码有些重复:创建错误,指定HTTP状态码,使用next(err)...

Fundebug是全栈JavaScript错误监控平台,支持各种前端和后端框架,可以帮助您第一时间发现BUG!

boom

boom是一个兼容HTTP的错误对象,他提供了一些标准的HTTP错误,比如400(参数错误)等。

const boom = require('boom')
app.get('/users/:id', (req, res, next) => {
  const userId = req.params.id
  if (!userId) {
    return next(boom.badRequest('missing id'))
  }

  Users.get(userId, (err, user) => {
    if (err) {
      return next(boom.badImplementation(err))
    }

    res.send(users)
  })
})

错误处理中间件需要稍作修改:

app.use((err, req, res, next) => {
  if (err.isServer) {
    // log the error...
    // probably you don't want to log unauthorized access
    // or do you?
  }
  return res.status(err.output.statusCode).json(err.output.payload);
})

Async/Await错误处理

使用Async/Await之后,可以这样处理Express异常:

  • 将中间件使用Promise封装起来,使用catch统一处理异常
  • 在中间件中,直接抛出异常就可以了
const boom = require('boom');
// wrapper for our async route handlers
// probably you want to move it to a new file
const asyncMiddleware = fn => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch((err) => {
    if (!err.isBoom) {
      return next(boom.badImplementation(err));
    }
    next(err);
  });
};
// the async route handler
app.get('/users/:id', asyncMiddleware(async (req, res) => {
  const userId = req.params.id
  if (!userId) {
    throw boom.badRequest('missing id')
  }

  const user = await Users.get(userId)
  res.json(user)
}))

参考

  • 验证HTTP请求参数可以使用joi模块
  • 打印日志可以使用winston或者pino模块
img_7bcf4937bf47efb2ed79508dc1de08f8.png

版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/12/06/handle-express-error/

目录
相关文章
|
3月前
|
中间件
Koa2 的错误处理机制是什么?如何捕获错误?
Koa2 的错误处理机制是什么?如何捕获错误?
38 0
|
10天前
|
程序员
项目中的全局异常是如何处理的
项目中的全局异常处理通常包括对预期异常(程序员手动抛出)和运行时异常的管理。项目已提供`BaseException`作为基础异常类,用于手动抛出异常,并通过`GlobalExceptionHandler`进行全局处理。`
23 4
|
16天前
|
前端开发 程序员
项目中异常是如何处理的
项目中设定了全局异常处理器,统一处理预期和运行时异常。预期异常由程序员手动抛出,用于异常情况的接口返回;运行时异常为不可控错误,提供统一返回格式便于前端提示和后端排查。全局异常处理器借助@RestControllerAdvice和@ExceptionHandler注解,前者标识处理器,后者按异常类型定制前端响应,如预期异常直接返回,运行时异常则调整响应内容。
13 0
|
6月前
|
中间件
93 # 实现 express 错误处理中间件
93 # 实现 express 错误处理中间件
27 0
|
9月前
|
运维 Prometheus 监控
java异常 | 处理规范、全局异常、Error处理
java异常 | 处理规范、全局异常、Error处理
|
8月前
|
数据采集 数据安全/隐私保护
如何使用异常处理机制捕获和处理请求失败的情况
在爬虫开发中,我们经常会遇到请求失败的情况,比如网络超时、连接错误、服务器拒绝等。这些情况会导致我们无法获取目标网页的内容,从而影响爬虫的效果和效率。为了解决这个问题,我们需要使用异常处理机制来捕获和处理请求失败的情况,从而提高爬虫的稳定性和稳定性。
如何使用异常处理机制捕获和处理请求失败的情况
|
索引 Python
Python基础 常见的异常类型 异常的捕获 异常的处理机制
python中常见的异常类型 1、ZeroDivisionError 除(或取模)零(所有数据类型) 2、IndexError #序列中没有此索引 3、KeyError #映射中没有这个键 4、NameError #未声明/初始化对象(没有属性) 5、SyntaxError #Python 语法错误 6、ValueError #传入无效的参数
Python基础 常见的异常类型 异常的捕获 异常的处理机制
express学习3-捕获错误
express学习3-捕获错误
92 0
express学习3-捕获错误
NestJS 7.x 折腾记: (6) 异常过滤器,取其精华去其糟粕!比如响应异常数据的包装~
正如官方所说: 内置的异常层负责处理整个应用程序中的所有抛出的异常。 当捕获到未处理的异常时,最终用户将收到友好的响应。
392 0
如何处理使用ngrx时遇到的错误消息: NullInjectorError R3InjectorError(AppModule)[StoreFeatureModule]
如何处理使用ngrx时遇到的错误消息: NullInjectorError R3InjectorError(AppModule)[StoreFeatureModule]
445 0
如何处理使用ngrx时遇到的错误消息: NullInjectorError R3InjectorError(AppModule)[StoreFeatureModule]

热门文章

最新文章