如何处理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/

目录
相关文章
|
5月前
|
机器学习/深度学习 监控 数据可视化
人体跌倒识别检测项目|全流程源码+数据集+可视化界面+一键训练部署
本项目基于 YOLOv8 模型和 PyQt5 图形界面工具,构建了一个 人体跌倒识别系统,旨在通过计算机视觉技术监测老年人等群体的跌倒行为。项目提供了完整的 源码、数据集、训练流程、以及开箱即用的检测程序,确保用户能够快速搭建并部署自己的跌倒识别系统。
人体跌倒识别检测项目|全流程源码+数据集+可视化界面+一键训练部署
|
存储 Oracle 关系型数据库
关系型数据库Oracle 空间不足
【7月更文挑战第16天】
310 2
|
人工智能 移动开发 前端开发
Markdown-to-Image:开源的在线 Markdown 转海报编辑器
Markdown-to-Image 是一款开源的在线 Markdown 转海报编辑器,能够将 Markdown 文本内容转换为图像,适用于创建社交媒体帖子、海报和其他视觉内容。该工具支持多种输出格式,并允许用户自定义样式,适用于多种应用场景。
1069 4
Markdown-to-Image:开源的在线 Markdown 转海报编辑器
|
移动开发 JavaScript API
Sprunki Game 实现技术分析及介绍
**Sprunki** 是一款基于音乐创作的游戏,作为经典游戏 **Incredibox** 的粉丝改版,它采用 HTML5 和 JavaScript 构建,通过拖拽式 UI 和模块化声音系统,提供了一个创意十足的音乐创作平台。游戏支持多种设备,并融入了 CSS3 动画和 Web Audio API,增强视觉与音效同步。玩家还可以通过社交媒体分享作品,参与社区互动。Sprunki 不仅是一款游戏,更是一个开放的创作平台。
|
存储 数据挖掘 Linux
探索Linux命令rpm2cpio:解析RPM包内容的利器
`rpm2cpio`是Linux下用于从RPM包中提取内容的工具,它将`.rpm`转换为CPIO归档。无需安装,可直接访问包内文件,适合数据分析。命令简单,常与`cpio`结合使用,如`rpm2cpio package.rpm | cpio -idmv`解压文件。示例包括提取特定文件和列出包内所有文件。注意权限、路径和文件完整性,使用前备份数据,并查阅文档以优化使用。
视频格式转换与DRM解除
随着流媒体平台的普及,用户对视频下载和转换工具的需求不断增加。本文介绍了几款优秀工具,如CleverGet、PlayOn Cloud、CocCut、StreamGaGa和PlayOn Desktop,帮助用户更好地下载、转换和管理视频内容。这些工具不仅提升了视频获取的便利性,还提供了多种选择,满足不同需求。使用时请确保合法合规。
|
机器学习/深度学习 人工智能 Cloud Native
秒速出图!体验 TensorRT 加速 Stable Diffusion 图像创作
秒速出图!体验 TensorRT 加速 Stable Diffusion 图像创作
141569 120
|
JavaScript 前端开发 API
全栈开发革命来临!Vue.js与Node.js联手,打造前后端无缝对接的奇迹之作!
【8月更文挑战第30天】在Web开发领域,前后端分离与协作至关重要。Vue.js以其轻量级和易用性深受前端开发者喜爱,而Node.js则以高性能和事件驱动特性在后端领域崭露头角。二者结合开启了全栈开发新篇章,通过RESTful API或GraphQL实现高效稳定通信。本文以示例说明如何使用Vue.js和Node.js构建全栈应用,从前端Vue组件到后端Express服务器,展示了数据获取与展示的全过程。这种组合提供了一种高效简洁的全栈开发方案,使开发者能更专注于业务逻辑实现。
1327 1
Echarts legend图例配置项 设置位置 显示隐藏
Echarts legend图例配置项 设置位置 显示隐藏
2522 0