node.js ERR_HTTP_HEADERS_SENT:发送到客户端后无法设置头

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52122272/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:53:55  来源:igfitidea点击:

ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client

node.jsexpressmongoosepassport.jsexpress-jwt

提问by lourdesr

I'm facing this weird issue in NodeJS when using with Passport.js, Express and Mongoose. Basically, I get an error saying "Cannot set headers after they are sent to the client" even though I don't send more than one header.

与 Passport.js、Express 和 Mongoose 一起使用时,我在 NodeJS 中遇到了这个奇怪的问题。基本上,即使我不发送多个标头,我也会收到一条错误消息“在将标头发送到客户端后无法设置标头”。

I've read other posts and tried them out as well, and none of them worked.

我已经阅读了其他帖子并尝试了它们,但都没有奏效。

I've dug through github issues and I can't seem to find a solution. I get the problem that this error is triggered when I send multiple response headers, but the fact is that I am not sending multiple headers. It seems just weird.

我已经挖掘了 github 问题,但似乎找不到解决方案。我收到的问题是,当我发送多个响应标头时会触发此错误,但事实是我没有发送多个标头。这似乎很奇怪。

This is my stack trace:

这是我的堆栈跟踪:

(node:9236) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.

Server Running on port 5000
MongoDB Connected Error
[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
  at validateHeader (_http_outgoing.js:503:11)
   at ServerResponse.setHeader (_http_outgoing.js:510:3)
   at ServerResponse.header (/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response.js:767:10)
   at ServerResponse.json (/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response.js:264:10)
   at Profile.findOne.then.profile (/Users/lourdesroashan/code/github/devlog/routes/api/profile.js:27:30)
   at <anonymous>

(node:9236) DeprecationWarning: 当前 URL 字符串解析器已被弃用,并将在未来版本中删除。要使用新的解析器,请将选项 { useNewUrlParser: true } 传递给 MongoClient.connect。

服务器在端口 5000 上运行
MongoDB 连接错误
[ERR_HTTP_HEADERS_SENT]:    在 ServerResponse.header 的 ServerResponse.setHeader (_http_outgoing.js:510:3)    处的
  validateHeader (_http_outgoing.js:503:11)
处将标头发送到客户端后无法设置标头
(/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response.js:767:10)
   在 ServerResponse.json (/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response。 js:264:10)
   在 Profile.findOne.then.profile (/Users/lourdesroashan/code/github/devlog/routes/api/profile.js:27:30)
   在 <匿名>

This is my server code:

这是我的服务器代码:

router.get("/userprofile", passport.authenticate('jwt', { session: false }), (req, res) => {

  Profile.findOne({ user: req.user.id }).then(profile => {
    if (!profile) {
      return res.status(404).json({ error: "No Profile Found" });
    }
    else {
      res.json(profile);
    }
  }).catch(err => {
    console.log(err);
  })
});

I understand what the error means, but from what I know, I don't think I am sending multiple headers, I even checked by console.log that only one of the blocks is run.

我明白错误意味着什么,但据我所知,我认为我没有发送多个标头,我什至通过 console.log 检查了只有一个块在运行。

Thank you so much in advance! :)

非常感谢您!:)

Full Code at: https://github.com/lourdesr/devlog

完整代码:https: //github.com/lourdesr/devlog

EDIT:

编辑:

I figured it out. It was a problem in my passport.js while trying to get the authenticated user. I forgot to use 'return' on the 'done' method, which had caused it. Just added the return statement and it worked!

我想到了。尝试获取经过身份验证的用户时,我的passport.js 出现了问题。我忘记在导致它的“完成”方法上使用“返回”。刚刚添加了 return 语句,它起作用了!

回答by jfriend00

That particular error occurs whenever you try to send more than one response to the same request and is usually caused by improper asynchronous code.

每当您尝试向同一请求发送多个响应时,就会发生该特定错误,并且通常是由不正确的异步代码引起的。

The code you show in your question does not appear like it would cause that error, but I do see code in a different route herethat would cause that error.

您在问题中显示的代码似乎不会导致该错误,但我确实在此处看到不同路径中的代码会导致该错误。

Where you have this:

你有这个:

if (!user) {
  errors.email = "User not found";
  res.status(404).json({ errors });
}

You need to change it to:

您需要将其更改为:

if (!user) {
  errors.email = "User not found";
  res.status(404).json({ errors });
  // stop further execution in this callback
  return;
}

You don't want the code to continue after you've done res.status(404).json({ errors });because it will then try to send another response.

您不希望代码在完成后继续,res.status(404).json({ errors });因为它随后会尝试发送另一个响应。



In addition, everywhere you have this:

此外,您到处都有:

if (err) throw err;

inside an async callback, you need to replace that with something that actually sends an error response such as:

在异步回调中,您需要将其替换为实际发送错误响应的内容,例如:

if (err) {
    console.log(err);
    res.sendStatus(500);
    return;
}

throwing inside an async callback just goes back into the node.js event system and isn't thrown to anywhere that you can actually catch it. Further, it doesn't send a response to the http request. In otherwords, it doesn't really do what the server is supposed to do. So, do yourself a favor and never write that code in your server. When you get an error, send an error response.

在异步回调中抛出只会返回到 node.js 事件系统中,而不会被抛出到您可以实际捕获它的任何地方。此外,它不会发送对 http 请求的响应。换句话说,它并没有真正做服务器应该做的事情。所以,帮自己一个忙,永远不要在你的服务器上写那些代码。当您收到错误时,发送错误响应。



Since it looks like you may be new here, I wanted to compliment you on including a link to your full source code at https://github.com/lourdesr/devlogbecause it's only by looking at that that I was able to see this place where the error is occuring.

由于看起来您可能是新来的,我想称赞您在https://github.com/lourdesr/devlog 中包含指向您的完整源代码的链接,因为只有通过查看我才能看到这一点发生错误的地方。

回答by TheDarkIn1978

I was receiving this error because of a foolish mistake on my part. I need to be more careful when referencing my other working code. The truly embarrassing part is how long I spent trying to figure out the cause of the error. Ouf!

我收到这个错误是因为我犯了一个愚蠢的错误。在引用我的其他工作代码时,我需要更加小心。真正令人尴尬的部分是我花了多长时间试图找出错误的原因。哎哟!

Bad:

坏的:

return res
  .send(C.Status.OK)
  .json({ item });

Good:

好的:

return res
  .status(C.Status.OK)
  .json({ item });

回答by Ivan of uganda

Sorry for the Late response, As per the mongoose documentation "Mongoose queries are not promises. They have a .then() function for co and async/await as a convenience. However, unlike promises, calling a query's .then() can execute the query multiple time"

抱歉回复晚了,根据 mongoose 文档“Mongoose 查询不是承诺。为了方便起见,它们有一个 .then() 函数用于 co 和 async/await。但是,与承诺不同,调用查询的 .then() 可以执行多次查询”

so to use promises

所以使用承诺

mongoose.Promise = global.Promise //To use the native js promises

Then

然后

var promise = Profile.findOne({ user: req.user.id }).exec()
promise.then(function (profile){
    if (!profile) {
      throw new Error("User profile not found") //reject promise with error
    }
    return res.status(200).json(profile) //return user profile      
}).catch(function (err){
    console.log(err); //User profile not found
    return res.status(404).json({ err.message }) //return your error msg
})

here is an nice article about switching out callbacks with promises in Mongoose

这是一篇关于在猫鼬中使用承诺切换回调的好文章

and this answer on mongooses promise rejection handling Mongoose right promise rejection handling

和这个关于猫鼬承诺拒绝处理猫鼬正确承诺拒绝处理的答案

回答by Matt Hippensteel

I got the same error using express and mongoose with HBS template engine. I went to Expressjs and read the docs for res.render, and it says // if a callback is specified, the rendered HTML string has to be sent explicitly. So I wasnt originally sending my html explicitly in the callback,. This is only for a contact form btw, not login info, albeit GET

我在使用带有 HBS 模板引擎的 express 和 mongoose 时遇到了同样的错误。我去了 Expressjs 并阅读了 res.render 的文档,它说 // 如果指定了回调,则必须显式发送呈现的 HTML 字符串。所以我最初并没有在回调中明确发送我的 html。顺便说一句,这仅适用于联系表格,而不是登录信息,尽管是 GET

//Original
let { username, email } = req.query;  //My get query data easier to read

res.status(200).render('index', { username, email });

//Solution without error. Second param sending data to views, Third param callback

res.status(200).render('index', { username, email }, (err, html)=>{
      res.send(html);
 });

回答by sina

you have to enable Promisesin your programm, in my case i enabled it in my mongoose schema by using mongoose.Promise = global.Promise. This enables using native js promises.

您必须Promises在您的程序中启用它,在我的情况下,我使用mongoose.Promise = global.Promise. 这使得使用native js promises.

other alternatives to this soloution is :

此解决方案的其他替代方案是:

var mongoose = require('mongoose');
// set Promise provider to bluebird
mongoose.Promise = require('bluebird');

and

// q
mongoose.Promise = require('q').Promise;

but you need to install these packages first.

但您需要先安装这些软件包。