statusRouter.route('/')
.all(function(req,res,next){
res.writeHead(200, {'Content-Type': 'application/json'});
next();
})
.get(function(req, res, next) {
res.json({
name : "xyz"
});
});
这会崩溃 - 标题无法在发送后设置。
但问题是,这有效:
statusRouter.route('/')
.all(function(req,res,next){
res.writeHead(200, {'Content-Type': 'text/plain'});
next();
})
.get(function(req, res, next) {
res.end("xyz");
});
注意:如果我在发送JSON的第一种情况下删除了writeHead函数,它也会开始工作。为什么当我写一个writeHead时它不起作用?这件事让我发疯,任何人都可以解释为什么会这样?
P.S我正在使用我自己的路由器使用快速生成的应用程序。
答案 0 :(得分:2)
Express res.writeHead()
和res.end()
都不是由Express实现的,而是由Node.js http
模块实现的。
其文档说明res.end()
:
如果指定了
data
,则相当于调用response.write(data, encoding)
后跟response.end(callback)
所以res.end("xyz")
简称:
res.write("xyz");
res.end();
对于res.write()
文档说明:
如果调用此方法并且尚未调用
response.writeHead()
,则它将切换到隐式标头模式并刷新隐式标头。
所以res.end("xyz")
实际简称:
if (! res.headersSent) {
res.writeHead(...);
}
res.write("xyz");
res.end();
这意味着在使用res.writeHead()
之前,在您自己的代码中发出res.end()
是完全可以的。在内部,http
模块会知道您已经刷新了标题,因此它不会再次执行(因此可以防止您获得的错误)。但是,一旦调用writeHead()
,您就无法设置不同的标头或更改现有的标头。
现在,res.json()
是另一回事:这不是http
模块的一部分,而是Express本身的一部分。由于它用于发送JSON响应,因此会将内容类型标题设置为application/json
(因此您不必这样做)。
但这只有在尚未发送标题时才有效:您已经发出标题时无法设置标题。这就是您收到错误的原因。
如果要在Express中设置特定标头,请使用res.set()
。
答案 1 :(得分:1)
Express按照添加顺序评估其路线。这意味着将首先执行传递给pip3 install ...
的路由处理程序。在此处理程序中,写入响应头,然后.all()
告诉Express继续迭代其路由列表以获得另一个可能的匹配路由。
然后匹配尝试发送JSON响应的next()
路由处理程序。但是,.get()
隐式发送响应头,并将作为JSON传递的值写入响应并结束响应。这就是为什么您看到有关.json()
被多次调用的错误。