繁体   English   中英

路线在快车中行驶后,为什么不能叫“下一个”?

[英]Why can't i call `next` after a route runs in express?

我有一条简单的路线,像这样:

// This is just a health check
const endpoint = (req, res, next) => {
  res.json({
    status: 'ok',
  });
  next();
};

router.get('/', endpoint);

我收到Error: Can't set headers after they are sent. 从快递。 即使我没有其他可能的下一个中间件要运行,或者即使我的next中间件实际上不执行任何操作并且是一个空函数,也是如此。

我对中间件和next工作方式缺少什么?

我认为您在自己的问题中回答了它:已发送回复后,您将无法对其进行任何处理。 如果您考虑一下,这是有道理的。 如果使用next来以某种方式修改请求,为什么在发送请求后,它仍然像“正在工作”一样“起作用”?

根据Express docs ,这是它们在get请求中使用next的方式:

app.get('/example/b', function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()
}, function (req, res) {
  res.send('Hello from B!')
})

如果您需要在该特定端点中执行其他操作,则正确的方法是在发送响应之前执行此操作。 它是快递架构工作的方式。

如果要对每个端点应用相同的逻辑(看起来像这样,因为您要检查req.pathreq.params和/或req.route ),则可以使用中间件来监听express的finish事件:

router.use((req, res, next) => {
  res.on('finish', function() {
    // extra logic here after sending response
  });
  next();
});

const endpoint = (req, res, next) => {
  res.json({
    status: 'ok',
  });
};

router.get('/', endpoint);

可能有几个问题:

最后,您有一个404处理程序(我们都这样做),却被忽略了。 例如:

app.get('/path', (req, res, next) => {
  res.json({ greet: "Welcome!" })
  next() // <-- calling next middleware
})

// set up a 404 handler at the end
app.use((req, res) => {
  res.status(404).send('Opps! Not Found');
})

这将导致错误Error: Can't set headers after they are sent. 因为您的404处理程序正在发送响应。

或者您偶然发现了一个未知功能 (或者很明显,您的一条路线未按预期运行,可能是设计错误)。 考虑以下路线:

app.get('/path/:id', (req, res, next) => {
  res.json({ message: "Welcome!" });
  next() // <-- calling next middleware
})

app.get('/path/test', (req, res, next) => {
  res.json({ message: "Welcome!" });
})

如果您的请求路径是/path/test则在/path/:id路由中调用next将导致错误(通常建议使用更好的路由实现)

一种了解middleware的简单方法, nextswitch语句的工作方式有关:

 function test(x) { switch (x) { case 'Oranges': console.log('Orange juice'); break; case 'Mangoes': // fall through case 'Papayas': console.log('Pickles'); break; case 'Banana': console.log('Milkshake'); // forgot the break case 'Apple': console.log('Apple Pie') break; default: console.log('Sorry, no ' + x + '.'); } } test('Banana') 

调用next就像fall through switch语句一样,也执行下一种情况。

因此,当您在一条路由中呼叫next一个并且request继续与要发送响应的另一route (意外匹配)相匹配时,您会发现自己被错误打招呼。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM