Express.js - 在“装饰器”中包装每个中间件/路由

时间:2017-06-02 10:59:15

标签: javascript node.js express middleware

我有一些Express.js实例和一些我希望包含在某些函数中的路由。例如:

const wrapper = (route) => {
  return (req, res, next) => {
    let result = route(req, res, next);

    // do some independent processing
  }
};

app.get('/', wrapper((req, res, next) => {
  // respond to request somehow
}));

虽然这很好用,但我不喜欢在每个路由或中间件上明确调用wrapper的想法,这需要进行此类处理。

有没有办法能够在某个包装器中包装每个必需的路由/中间件(假设wrapper函数可以检查这个路由/中间件需要被包装)隐式地(通过Express.js扩展名,猴子修补或一些特殊的中间件)?

更新

更坚实的例子。我们假设我想制作async路由器功能。但我不想在每个路线功能中发现错误。所以我把它们包起来:

const wrapper = func => (req, res, next) => {
  const promise = func(req, res, next);

  if (promise.catch) {
    promise.catch(err => next(err));
  }

  next();
};

app.get('/one', wrapper(async (req, res, next) => {
  // respond to request somehow
}));

app.get('/two', wrapper(async (req, res, next) => {
  // respond to request somehow
}));

app.get('/three', wrapper(async (req, res, next) => {
  // respond to request somehow
}));

// and so on...

app.use((err, req, res, next) => {
  // do something with intercepted error
});

所有路线周围的显式wrapper实际上是我想要摆脱的东西。

2 个答案:

答案 0 :(得分:2)

事实证明它有点像PITA,因为最终,Express不会传播路由处理函数的返回值。

这就是我提出的(猴子补丁):

const Layer          = require('express/lib/router/layer');
const handle_request = Layer.prototype.handle_request;

Layer.prototype.handle_request = function(req, res, next) {
  if (! this.isWrapped && this.method) {
    let handle  = this.handle;
    this.handle = function(req, res, next) { // this is basically your wrapper
      let result = handle.apply(this, arguments);
      // do some independent processing
      return result;
    };
    this.isWrapped = true;
  }
  return handle_request.apply(this, arguments);
};

我可能会建议使用与express-promise-router类似的方法,它实现了Express'Router的直接替换。但是,这并不是隐含的。

答案 1 :(得分:0)

为什么不使用next()?

您可以在需求上添加内容,例如

app.get('/', (req, res, next) => {
    req.somestupidfieldthatidontevenknowwhyinamedthisway = 42;
    next();
});

app.get('/', (req, res, next) => {
    //req.somestupidfieldthatidontevenknowwhyinamedthisway is now accessible as 42
    var valueFromPreviousMiddleware = req.somestupidfieldthatidontevenknowwhyinamedthisway;
    .....
});