[英]I can't understand why my express route is encountering 'can't set headers after they are sent'
[英]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.path
, req.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
的简单方法, next
与switch
语句的工作方式有关:
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.