如何解决“将标头发送到客户端后无法设置标头”

Posted

技术标签:

【中文标题】如何解决“将标头发送到客户端后无法设置标头”【英文标题】:How can i resolve 'Cannot set headers after they are sent to the client' 【发布时间】:2019-02-28 19:20:30 【问题描述】:

如何解决Cannot set headers after they are sent to the client:

app.js

var express = require('express');
var session = require('express-session');
var mongoose = require('mongoose');
var app = express();
var ejs = require('ejs');
var port = 3000;
var bodyParser = require('body-parser');
var mongoDB = "mongodb://localhost:27017/vinavdb";

app.set('views', __dirname + '/admin') app.engine('html', ejs.renderFile);
app.set('view engine', 'ejs');

app.set('trust proxy', 1);
app.use(session(
  secret: 'dsghbrtdfhbdfg64545TRYFFHGGJNN',
  resave: false,
  saveUninitialized: true
))

app.use(bodyParser.json());
app.use(bodyParser.urlencoded(
  extended: true
));

var sess;

mongoose.Promise = global.Promise;
mongoose.connect(mongoDB, 
  useNewUrlParser: true
);

var nameSchema = new mongoose.Schema(
  firstname: String,
  lastname: String,
  email: String,
  password: String
);
var User = mongoose.model("User", nameSchema);

app.get("/", (req, res) => 
  sess = req.session;
  if (sess.email) 
    res.redirect("/admin");
   else 
    res.sendFile(__dirname + "/index.html");
  

);

app.get("/login", (req, res) => 
  res.sendFile(__dirname + "/login.html");
);
app.post("/addname", function(req, res) 
  var myData = new User(req.body);
  User.findOne(
    email: req.body.email
  , function(err, resv) 
    if (resv == null) 
      myData.save().then(item => 
        res.send("Name saved to database")
      ).catch(err => 
        res.status(400).send("Unable to save to database");
      );
      res.send("ThankYou For your Registration")
     else if (resv.email == req.body.email) 
      res.send("Email is already registered");
     else 
      res.send("Srry data is not allowed");
    
  );
);

app.post("/login", function(req, res, next) 
  User.findOne(
    email: req.body.email
  , function(err, vals) 
    if (vals == null) 
      res.end("Invalid Logins");
     else if (vals.email == req.body.email && vals.password == req.body.password) 
      sess = req.session;
      sess.email = req.body.email;
      res.redirect('/admin');
     else 
      res.send("Srry data is not allowed");
    
  );
);
app.route('/admin').get(function(req, res, next) 
  sess = req.session;
  if (sess.email) 
    res.send(__dirname + "/admin/index.html");
   else 
    res.write('Please login first.');
  
)

app.listen(port, () => 
  console.log("Server listening on port " + port);
);

【问题讨论】:

如果您想获得帮助,那么您至少应该花时间以可读的方式格式化代码。此外,您必须说明何时(针对哪条路线)发生此错误。 你必须放弃res.send("ThankYou For your Registration")线。 当我添加 "res.send(__dirname + "/admin/index.html");"这一行。我收到“'在将标头发送到客户端后无法设置标头'”此错误消息 @AmitVerma User res.sendFile 而不是 res.send 因为您发送的是 html 文件而不是数据。 【参考方案1】:

您的错误原因:您正尝试将单个请求的响应发送两次。

一个请求有一个响应。

一旦发送响应,您就不能再次为同一个请求发送它。在您的/addname API 中,您尝试发送响应两次。所以删除一个。

这里.save()是异步函数,所以节点不会等待并执行 res.send("ThankYou For your Registration") 第一次和稍后保存记录后,它将尝试发送res.send("Name saved to database"),因此您在这里遇到错误。

app.post("/addname", function(req, res) 
  var myData = new User(req.body);
  User.findOne(
    email: req.body.email
  , function(err, resv) 
    if (resv == null) 
      myData.save().then(item => 
              console.log("Name saved to database")
              res.send("ThankYou For your Registration")
      ).catch(err => 
        res.status(400).send("Unable to save to database");
      );
     else if (resv.email == req.body.email) 
      res.send("Email is already registered");
     else 
      res.send("Srry data is not allowed");
    
  );
);

【讨论】:

【参考方案2】:

执行 res.send 后,您不能在同一个请求中再次调用它,它只允许每个请求一个响应。在您的代码中,我认为这部分可能会发生:

if (resv == null) 
      myData.save().then(item => 
        res.send("Name saved to database")
      ).catch(err => 
        res.status(400).send("Unable to save to database");
      );
      res.send("ThankYou For your Registration")
    

在这种情况下,如果您在保存 myData 时发送了一个响应,但您之前已经异步发送了另一个响应(“ThankYou For your Registration”)。

希望对你有帮助

【讨论】:

当我添加 "res.send(__dirname + "/admin/index.html");"这一行。我收到“'在将标头发送到客户端后无法设置标头'”此错误消息

以上是关于如何解决“将标头发送到客户端后无法设置标头”的主要内容,如果未能解决你的问题,请参考以下文章

将标头发送到客户端后无法设置标头-请帮助我在代码中理解这一点

Node.js,Express:将标头发送到客户端后无法设置标头

GraphQL 突变“在将标头发送到客户端后无法设置标头”

Firebase 云功能错误:“在将标头发送到客户端后无法设置标头”

将标头发送到客户端后无法设置标头-Nodejs + AWS-S3 getObject

为啥我不断收到“错误 [ERR_HTTP_HEADERS_SENT]:将标头发送到客户端后无法设置标头”错误?