编写中间件,它不知道它在堆栈中的位置

时间:2016-04-03 16:29:09

标签: javascript node.js express callback middleware

我对Node / Express感到满意。我试图创建一个基本的REST api,并且我想知道如何处理这种困境。

假设我有一个控制器接收一个请求(在身份验证/其他中间件组件完成了他们的事情之后)调用模型函数来获取一些数据,如下所示:

module.exports = function (router) {
    router.get('/api/resource1', a_model.get_all);
};

模型的定义如下:

exports.get_all = function (req, res, next) {
  db.any('select * from resource_table')
  .then(function (data) {
    res.status(200).json({
      status: 'success',
      data: data,
      message: 'Retrieved all the things.'
    });
  })
  .catch(function (err) {
    return next(err);
  });
};

但现在让我说我有另一个控制器也需要调用该模型函数,但还需要对数据做一些其他的事情。 E.G。

module.exports = function (router) {
    router.get('/api/resource2', a_model.get_all, do_stuff_with_data);
};

a_model.get_all的当前状态不允许do_stuff_with_data执行操作"因为它永远不会调用next()

问题在于,如果我在变异next()后调用res,我会在Error: Can't set headers after they are sent时收到错误消息:/api/resource1

我尝试了if (next) { next(); },但这并不起作用,因为总是在堆栈底部发现错误捕获中间件。

一种可能的解决方案是在我的中间件链的末尾放置一个等同于NOP的函数,从而允许我的模块始终调用next(),但必须有更好的方法,对?

1 个答案:

答案 0 :(得分:3)

首先,您只能有一个发送响应的中间件处理程序。因此,您必须构建代码,以便只在一个地方发送对传入的http请求的响应,并且应该组织您的代码,以便非常清楚如何以及何时起作用。

然后,如果您希望有多个中间件处理程序为处理程序做出贡献,那么它们都可以检查传入的req对象,并且都可以向res对象提供信息。然后,后续处理程序可以使用和访问任何该信息。

例如,一个中间件处理程序可以运行数据库查询,处理该查询,然后将一些结果作为信息放入res对象,然后在处理此请求期间可供后续中间件处理程序使用。< / p>

另一个处理程序可以进一步处理数据,每个处理程序都通过调用next()将其传递给下一个数据。

然后,最后一个处理程序可以发送实际的响应,并且该处理程序不应该调用next(),因为它现在已经发送了响应,因此需要完成响应。

所以,也许你需要从实际发送响应的代码中分离出你的中间件(它只为最终响应准备数据)。只有当某些中间件处理程序依赖于先前中间件处理程序的处理时,您的中间件才需要处于适当的顺序。

然后,实际使用先前中间件处理结果发送最终响应的代码必须在其他中间件之后。通常这是一个特定的路由而不是中间件处理程序,但有时中间件可能会发送最终响应。