youngwind / blog

梁少峰的个人博客
4.66k stars 385 forks source link

自己动手写express中间件 #45

Open youngwind opened 8 years ago

youngwind commented 8 years ago

express本质上是由一系列中间件构成的,就像管道一样。

普通中间件

比如说,我要编写一个这样的中间件:假如请求中有date参数,那么给请求加上a参数,给返回加上b属性,然后交给下一个中间件处理。假如请求中没有date参数,直接返回message:"没有date“,结束响应。

// date.js
module.exports = function () {
  return function (req, res, next) {
    if (req.query.date) {
      req.a = "a";
      res.b = "b";
      //下一个中间件就可以读取到req.a和res.b参数了。
      next();
    } else {
      res.send({
        "code": 0,
        "message": "没有date"
      });
    }
  }
};

如果想在应用层级使用它,可以这样写:

var date = require('./date.js');
app.use(date());

如果想在路由层级使用它,可以这样写:

var date = require('./date.js')
router.use(date());

其实没有本质的区别。

错误处理中间件

错误处理中间件的特殊点在于它有四个参数。 准确地说,必须有四个参数才会被认为是错误处理中间件。如果只有三个参数,也会被认为是普通中间件,而且你也没法在里面进行错误处理。 当错误发生的时候,执行流会跳过所有的普通中间件,但是不会跳过错误处理中间件。

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

如何触发错误?

  1. new Error然后next()传递
// 这是一个捕获404错误的中间件
// 注意,这是一个普通的中间件,它只产生错误,并不处理错误
// 通过next(err)把错误传递给下一个**错误处理中间件**
app.use(function (req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

2.new Error 然后throw

app.use(function (req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  throw err;
});

参考资料: http://expressjs.com/zh-cn/guide/writing-middleware.html