【问题标题】:Sails Error:throw new Error('Can\'t set headers after they are sent.')Sails Error:throw new Error('Can\'t set headers after they are sent.')
【发布时间】:2015-07-03 13:59:10
【问题描述】:

您好,我是 Sails 的新手,我正在尝试通过禁用水线功能使用 Sails 连接到 Mongoose。在 Sails 中执行我的代码以进行 POST 操作时,我遇到了以下问题

/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:108
 if (this.ended && !this.hasRejectListeners()) throw reason;
                                                  ^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.res.setHeader (/usr/local/lib/node_modules/sails/node_modules/express/node_modules/connect/lib/patch.js:133:22)
at ServerResponse.res.set.res.header (/usr/local/lib/node_modules/sails/node_modules/express/lib/response.js:577:10)
at ServerResponse.res.send (/usr/local/lib/node_modules/sails/node_modules/express/lib/response.js:142:12)
at ServerResponse.res.json (/usr/local/lib/node_modules/sails/node_modules/express/lib/response.js:223:15)
at EventEmitter.<anonymous> (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/api/controllers/Status-packetController.js:74:17)
at EventEmitter.<anonymous> (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:175:45)
at EventEmitter.emit (events.js:110:17)
at Promise.safeEmit (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:81:21)
at Promise.fulfill (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:94:24)
at Promise.resolve (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/lib/promise.js:113:23)
at model.<anonymous> (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/lib/document.js:1578:39)
at next_ (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/hooks-fixed/hooks.js:89:34)
at EventEmitter.fnWrapper (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/hooks-fixed/hooks.js:171:15)
at EventEmitter.<anonymous> (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:175:45)
at EventEmitter.emit (events.js:110:17)
at Promise.safeEmit (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:81:21)
at Promise.fulfill (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:94:24)
at p1.then.then.self.isNew (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/lib/model.js:254:27)
at newTickHandler (/Users/febinp/Documents/Tecsol/Taqua/Taqua-loginpacket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:229:18)
at process._tickDomainCallback (node.js:381:11)

我的代码如下

CreateStatus: function (req, res) {
  var params = req.body;
  if(params.SerialNo == null) {
    var response = {};
    response.success = "FALSE";
    response.error = "Serial.NO.is.Null";
    res.json(response);
    return(res);
  }
  // For Authenfication purpose Only
  var mongoose = require('mongoose');
  var login = mongoose.model('Login');
  var SerialNo1 = req.body.SerialNo;

  login.find({ "SerialNo": SerialNo1 }, function (err,data) {
    if(err) {
      res.json({
        success: false,
        error: err
      });
      return;      
    } else {
      if(data.length <= 0) {
        res.json({
          success: false,
          error: "User Doesn't Exists"
        });
        return;          
      }  
    }
  });
  // End of Authentification  

  var msg_parts = params.msg_parts;


  // CONVERSION ALGORITHM FROM INTEGER TO BOOLEAN
  if(msg_parts.chargingStatus <= 0)
    msg_parts.chargingStatus = false;
  else
    msg_parts.chargingStatus = true;

  if(msg_parts.alarmInfo <= 0)
    msg_parts.alarmInfo = false;
  else
    msg_parts.alarmInfo = true;

  if(msg_parts.gpsStatus <= 0)
    msg_parts.gpsStatus = false;
  else
    msg_parts.gpsStatus = true;

  msg_parts.SerialNo = params.SerialNo; // Adding the Serial no into the message parts
  // CONVERSION ALGORITHM FROM INTEGER TO BOOLEAN finished

  var statuspacket = db.StatusPacket(msg_parts);
  // For saving into the Database
  statuspacket.save(function (err,data) {
    if(err) {
      res.json({
        success: false,
        exception: err
      });
      return;
    }
    res.json({
      success: true,
      data:data
    });
    return;  
  });
}

基本上,我的代码只是将数据输入数据库,然后在执行之前执行用户的身份验证部分。一旦我到 DHCP 并点击发布,我遇到了上面提到的问题。我的数据正在存储到数据库中,但帆正在下降。我的架构如下

// Serial No of the device.We require an Index on this column
SerialNo: {
  type: String,
  required: true
},
batteryLevel: {
  type: Number,
  min: 0, // battery level will take values from 0 to 6(0,1,2,3,4,5,6)
  max: 6
},
signalLevel: {
  type: Number,
  min: 0, // Signal Level will take values from 0 to 4 (0,1,2,3,4)
  max: 4,
},
chargingStatus: {
  type: Boolean,   
  default: false
},
alarmInfo: {
  type: Boolean,
  default: false
},
gpsStatus: {
  type: Boolean
},
createdAt: {
  type: Date,
  default: Date.now
},
PurgeDataNumber: {
  type:Number
}

我的路线

'/Status-packet/CreateStatus': 'Status-packetController.CreateStatus',
'/Status-packet/FindStatus': 'Status-packetController.FindStatus'

有人可以帮我解决这个问题,为什么我的sails 应用程序在后期操作中失败了吗?

【问题讨论】:

    标签: node.js mongoose sails.js waterline


    【解决方案1】:
    Error: Can't set headers after they are sent.
    

    正如@nfleury 所说,当您尝试多次向客户端发送响应 (res.*) 时会引发此错误。

    让我们找到问题。

    乍一看,没有问题。每次使用 res.json 时,您都会调用 return

    那么问题一定更复杂。可能是异步函数的问题?

    CreateStatus: function (req, res) {
      // No problem at the beginning
      // ... 
    
      // Here you call an asynchronous function
      // Let's name it "function 1"
      login.find({ "SerialNo": SerialNo1 }, function (err, data) {
        if(...) {
          res.json(...);
          return;      
        }
      });
      // You've called function 1 but the code continues to be executed
    
      // ...
    
      // Another async function is called
      // Let's name it "function 2"
      statuspacket.save(function (err, data) {
        res.json(...);
        return;  
      });
    }
    

    正如我们所见,函数 1 和 2 都被调用了。我假设调用回调时会出现问题。

    函数 2 回调始终向客户端发送响应。如果验证了一系列条件,函数 1 回调发送响应。明白了!

    现在。我们该如何解决?

    我认为您想要做的是等到第一个回调被调用后再继续。你可以这样做:

    login.find({ "SerialNo": SerialNo1 }, function (err, data) {
      // Function 1 has complete
      if(...) {
        res.json(...);
        return;      
      }
    
      // ...
    
      statuspacket.save(function (err, data) {
        res.json(...);
        return;  
      });
    });
    

    【讨论】:

    • 就我而言,找到多余的 res.send() 就可以了。谢谢!
    【解决方案2】:
    Error: Can't set headers after they are sent.
    

    通常当您遇到此错误时,这意味着您发送了两次响应...

    可能是这个原因:

    statuspacket.save(function (err,data) {
      if(err) {
        res.json({
          success: false,
          exception: err
        });
        return;
      }
      res.json({
        success: true,
        data: data
      });
      return;  
    });
    

    如果您有错误,它将再次发送 json 响应...看起来您在这里缺少“else”...

    【讨论】:

    • 你的第一句话是对的。但是由于他使用return,所以没有更多的事情发生。所以你在答案的第二部分是错误的。
    猜你喜欢
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 1970-01-01
    相关资源
    最近更新 更多