• connect
    connect是一个框架,它使用被称为中间件的模块化组件,以可重用的方式实现Web程序中的逻辑。在connect中,中间件组件是一个函数,它拦截HTTP服务器提供的请求和响应对象,执行逻辑,然后结束响应或者传递给下一个中间件组件。connect用派分器把中间件“连接”在一起.如下图所示:

  • connect工作机制
    在connect中,中间件组件是一个Javascript函数,通常它会接收三个参数:请求对象、响应对象以及next的回调函数。next回调函数表明当前这个组件(中间件)已经完成了它的工作,可以执行下一个中间件组件了。

  • 中间件的创建和使用

    1. 创建中间件,以logger中间件为例

      1
      2
      3
      4
      function logger(req, res, next) {
      console.log('s% s%', req.method, req.url);
      next();
      }
    2. 要在程序中使用中间件,调用use()方法,然后将中间键函数传给它

      1
      2
      3
      4
      const connect = require('connect');
      const app = connect();
      app.use(logger); // 使用中间件
      app.listen(3000);

  • 创建和使用可配置的中间件
    以上简单的介绍了中间件的创建和使用。下面我们来创建可配置的中间件

    1. 为了向开发人员提供可配置的能力,中间件通常会遵循一个惯例:用函数返回另一个函数(闭包).

      1
      2
      3
      4
      5
      6
      function setup(option){
      // 中间件初始化逻辑
      return function(req, res, next){ // 被返回的函数
      // 中间件逻辑
      }
      }
    2. 使用可配置的中间件

      1
      app.use(setup({some: 'option'}))

  • 错误处理中间件

    1. connect的默认错误处理器
      默认情况下,connect给出的响应是500,包含文本’Internet Server Error’以及错误自身详细信息的响应主体

      1
      2
      3
      4
      5
      6
      const connect = require('connect');
      connect().use(function(req, res){
      foo() // 没有定义会报错
      res.setHeader('conetnt-type': 'text/plain');
      res.end();
      }).listen(3000);
    2. 自行处理程序错误
      错误处理中间件函数必须接受4个参数:err,req,res,next。普通的中间件函数接收3个参数:req,res,next。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      const errorHandle = () => {
      const env = process.env.NODE_ENV || 'development';
      return (err, req, res, next) {
      res.statusCode = 500;
      switch (env) {
      case 'development':
      res.setHeader('content-type': 'application/json');
      res.json(JSON.stringify(err));
      break;
      default:
      res.end('Server Error');
      }
      }
      }
      connect()
      .use(router(require('./routers/user'))) // 跳过
      .use(router(require('./router/admin'))) // 跳过
      .use(errorHandle); // 处理错误

    在错误发生时的connect流程如下图所示