express请求流中的错误捕捉处理

nodejs中的错误处理还是比较麻烦的,尤其遇到异步回调之类,多层嵌套,简单的try…catch无法处理。

目前在用expressjs,拿此举例说说怎样实践。
第一种,从一介布衣那儿看到的方法,可行:

const domain = require('domain');
app.use((req, res, next) => {
  const reqDomain = domain.create();
  // next抛出的异常在这里被捕获,触发此事件
  reqDomain.on('error', e => {
    // ... 这里统一处理错误,比如渲染或跳转到404,500页面
  });

  return reqDomain.run(next);
});

通过在route定义之前添加如上的中间件,可以捕捉到大部分的错误。

第二种,上面说到是大部分的错误,因为我碰到了一个没成功捕捉到的,就是使用swig模板渲染时的变量报错。

// 设置模板引擎
app.engine('swig', swig.renderFile);
app.set('view engine', 'swig');
app.set('views', `${__dirname}/views`);
app.set('viewExt', '.swig');
// 在某处渲染输出: 
res.render('template/filepath');
// 如果在filepath.swig文件中有变量报错,则第一种方法不能成功捕捉

这时在stackoverflow找到一个方法,

// 依然按第一种方法写错误捕捉
// 然后在route之后再写个中间件

// 最后的错误处理,比如发生在res.render中的错误
// 由于已经设置了响应,因此只能发送状态码,或跳转
// next不能去除,否则无法获取到错误
app.use((err, req, res, next) => {
  // res.sendStatus(500);
  log.error(err);
  // res.redirect(301, '/'); // 跳转到首页
  next();
});

ok,经过验证,上述方法已经能够处理目前所有遇到的问题。

第三种,为什么会有这一种方法呢,纯属个人思维发散,由于是express内部处理了模板引擎,导致res.render方法不能正常抛出错误被外围捕捉,那么我直接用swig方法渲染文件,并把渲染后的结果通过res.send方法响应是不是可以呢?

// 之前是这样渲染的
res.render('template/filepath');
// 改为
res.send(swig.renderFile('/...这里应该是物理绝对路径.../template/filepath.swig'));

经过上面改造,发现只用第一种方法也可以正常捕捉到错误,说明推论正确。

之所以在第二种还能解决的情况下还在寻找其他方案,是因为第二种的最终错误处理只能响应状态码,而不能再渲染页面了。终究不够完美,方法不够优雅。

像第三种方式,完全可以不必设置express的模板引擎了,用res.send + 模板自身的渲染方法即可,封装为一个方法,方便调用。

http://cssor.com/express-handle-error.html

参与评论

电子邮件地址不会被公开。 必填项已用*标注

*

全部分类
Books(4)code(7)database(6)html&css(24)java(11)JavaScript(48)jQuery(24)linux(20)python(1)React(1)share(1)soft(4)solution(53)thinking(17)vim(9)WordPress(8)前端优化(12)拓展(33)服务器(31)移动开发(4)自然(22)