代码之家  ›  专栏  ›  技术社区  ›  mark

在expressjs中设置请求清理中间件

  •  7
  • mark  · 技术社区  · 11 年前

    我正在尝试使用postgresql作为后端编写一个expressjs服务器。每个请求都通过调用 pg.connect 获取池连接( client )以及在不再需要连接时将其返回到池的方法( done ). 例如:

      function dbConnect(req, res, next) {
        if (res.locals.pgCtx) {
          next();
          return;
        }
    
        pg.connect(dbConn, function (err, client, done) {
          if (err) {
            res.send(500, err.message);
          } else {
            app.locals.pgCtx = res.locals.pgCtx = {
              client: client,
              done: done
            };
            next();
          }
        });
      }
    
      app.use(allowCrossDomain);
      app.use(express.methodOverride());
      app.use(express.compress());
      app.use(express.bodyParser());
      app.use(express.logger());
      app.use(passport.initialize());
      app.use(express["static"](webRootDir));
      app.use(dbConnect);                       // <--------------
      app.use(authenticate);
      app.use(app.router);
      app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
      app.set('view engine', 'jade');
      app.set('views', webRootDir);
      app.engine("jade", jade.__express);
    
      indexHandlers = [fetchConstData, function (req, res) {
        res.render(templatesDir + 'index', {
          constData: app.locals.constData,
          env: app.get('env'),
          user: req.user,
          admin: isAdmin(req.user.role),
          host: req.host
        });
      }];
      app.get('/', indexHandlers);
      app.get('/index', indexHandlers);
      app.get('/index.html', indexHandlers);
    

    我的问题是,虽然我可以插入 dbConnect 作为在请求的任何其他中间件之前运行的全局中间件,我还需要能够在所有中间件运行之后进行清理,以便将连接返回到池中。

    理想情况下,无论请求如何结束,都应该有一种方法来指定在所有特定于请求的中间件运行后要运行的全局中间件,方法是:

    • res.send(...)
    • 引发异常
    • 将err对象传递到 next()

    请注意,任何特定于请求的中间件都可以通过这种方式终止链。

    现在我只能看到这种方法:

    1. 通过注册一个自定义的全局错误处理程序中间件而不是 express.errorHandler .
    2. 更换 res.send 中的方法 res 对象,该自定义版本先将连接返回到池,然后继续到原始连接 重新发送 实施

    所有这些都有一股浓浓的黑客气息。我想做对,所以我想问有没有一种方法可以注册像请求清理中间件这样的东西?

    编辑

    静态内容处理程序必须移动到 数据库连接 中间件,否则我们会泄漏数据库连接,直到没有更多的连接可用,并且服务器无法提供任何服务,因为 数据库连接 永远不会返回等待释放连接。

    1 回复  |  直到 11 年前
        1
  •  15
  •   robertklep    11 年前

    有一个 finish 可以在响应对象上侦听的事件,该事件将在响应完成时发出:

    function dbConnect(req, res, next) {
      res.on('finish', function() {
        // perform your cleanups...
      });
      ...
    }