【发布时间】:2015-10-08 08:35:19
【问题描述】:
如果条件为真,我正在尝试使用 Mongoose 函数 findById 发送错误。问题是 Mongoose 似乎正在设置 res Express 对象,然后当我尝试自己设置标题时抛出错误。代码如下:
console.log(res.headersSent); // false
Trade.findById(req.body.trade, function (err, trade) {
if (err) throw err;
// Ensure user is not making an offer on their own item
Item.findById(trade.listing, function (err, item) {
if (err) throw err;
if (req.decodedId == item.user) {
console.log(res.headersSent); // true (?)
return res.status(403).send({
success: false,
message: 'You cannot make an offer on your own item'
})
} else {
return;
}
})
这是错误的堆栈跟踪:
false // res.headersSent() before calling Trade.findById()
POST /api/v2/offer 200 148.799 ms - 162
true // res.headersSent() after calling Item.findById() and checking error condition
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (/Users/Matt/Dropbox/work/TradeRate/prototype/node_modules/express/lib/response.js:700:10)
at ServerResponse.send (/Users/Matt/Dropbox/work/TradeRate/prototype/node_modules/express/lib/response.js:154:12)
at ServerResponse.json (/Users/Matt/Dropbox/work/TradeRate/prototype/node_modules/express/lib/response.js:240:15)
at ServerResponse.send (/Users/Matt/Dropbox/work/TradeRate/prototype/node_modules/express/lib/response.js:142:21)
at /Users/Matt/Dropbox/work/TradeRate/prototype/server/controllers/offers.js:48:40 // LINE THAT CONTAINS return res.status(403).send ...
at /Users/Matt/Dropbox/work/TradeRate/prototype/node_modules/mongoose/lib/query.js:1169:16
at /Users/Matt/Dropbox/work/TradeRate/prototype/node_modules/mongoose/node_modules/kareem/index.js:103:16
at process._tickCallback (node.js:355:11)
18 Jul 15:26:39 - [nodemon] app crashed - waiting for file changes before starting...
什么可能导致此错误? Mongoose API 是否有设置我缺少的响应标头的方面?
编辑:我添加了完整的(更新的)导出路由处理程序,以防有一些上下文可以使问题更清楚。
// POST /api/offer
exports.createOffer = function (req, res, next) {
console.log(res.headersSent);
Trade.findById(req.body.trade, function (err, trade) {
if (err) {
next(err);
return;
} // not good to throw from async events, let express' error handling middleware take care of it
// Ensure user is not making an offer on their own item
Item.findById(trade.listing, function (err, item) {
if (err) {
next(err);
return;
}
if (req.decodedId == item.user) {
console.log(res.headersSent); // true (?)
res.status(403).send({
success: false,
message: 'You cannot make an offer on your own item'
});
}
// all done with async stuff, pass the request long
next();
});
// If trade is expired, reject the offer
if (trade.expiresOn < Date.now()) {
res.status(403).send({
success: false,
message: 'This trade has expired and cannot accept new offers'
});
}
// Create new offer and add data
var newOffer = new Offer();
newOffer.items = req.body.items;
newOffer.trade = req.body.trade;
newOffer.save(function (err, offer) {
if (err) throw err;
});
// Add offer to items in offer
for (var i = 0; i < req.body.items.length; i++) {
Item.findById(req.body.items[i], function (err, item) {
if (err) throw err;
item.offers.push(newOffer._id);
item.save(function (err, item) {
if (err) throw err;
});
});
}
// Add offer to trade
trade.offers.push(newOffer._id);
trade.save(function (err, trade) {
if (err) throw err;
});
return res.send(newOffer);
});
};
【问题讨论】: