博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何处理Express异常
阅读量:7038 次
发布时间:2019-06-28

本文共 2602 字,大约阅读时间需要 8 分钟。

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

  • 原文:
  • 译者:

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

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

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

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)...

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

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 fileconst 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 handlerapp.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请求参数可以使用模块
  • 打印日志可以使用或者模块

欢迎加入我们的Fundebug技术交流3群: 490454644。

版权声明:

转载时请注明作者Fundebug以及本文地址:

你可能感兴趣的文章
在Objective-C中浅谈面向对象
查看>>
iOS开发Swift篇—(二)变量和常量
查看>>
java路径中的空格问题(转)
查看>>
mac 版本号控制工具SmartSVN7.5.4(破解版)
查看>>
[Ubuntu] 如何设置静态 IP 和 DNS
查看>>
递归、非递归 反转单链表
查看>>
java的System.getProperty()方法能够获取的值
查看>>
内层元素设置position:relative后父元素overflow:hidden overflow:scroll失效 解决方法
查看>>
020 <one-to-one>、<many-to-one>单端关联上的lazy(懒加载)属性
查看>>
.Net中的7Zip——Sharpcompress
查看>>
Android_PendingIntent的使用
查看>>
VS2010 C++环境下DLL和LIB文件目录及名称修改
查看>>
【iOS XMPP】使用XMPPFramewok(三):好友状态
查看>>
linux 信号处理 四
查看>>
Linux 查看支持的语言,日期,时间,计算器
查看>>
javaWeb学习总结(10)- Filter(过滤器)学习
查看>>
在Linq to sql 和 Entity framework 中使用lambda表达式实现left join
查看>>
ENC28J60
查看>>
Web service是什么?
查看>>
php 简单连接数据库的操作
查看>>