如何在node.js中处理错误而不设置两次res头
当我使用异步调用时,我对节点的如何在node.js中处理错误而不设置两次res头,node.js,express,asynchronous,response-headers,Node.js,Express,Asynchronous,Response Headers,当我使用异步调用时,我对节点的req,res参数以及处理这些参数的最佳方法有点困惑。我目前拥有的一个函数应该是向我的数据库添加一个项,相应地更新一些数据库模型,然后发送一个响应,说更新成功。但是,如果发生错误,此函数异步调用的函数可能会发送错误响应。如果发生这种情况,则会出现错误发送后无法设置标题,因为我尝试调用res.send两次。如果有人能帮助我们找出一种处理错误的最佳方法,我们将不胜感激。谢谢 主要功能: item.author = req.user._id; item.descripti
req,res
参数以及处理这些参数的最佳方法有点困惑。我目前拥有的一个函数应该是向我的数据库添加一个项,相应地更新一些数据库模型,然后发送一个响应,说更新成功。但是,如果发生错误,此函数异步调用的函数可能会发送错误响应。如果发生这种情况,则会出现错误发送后无法设置标题
,因为我尝试调用res.send
两次。如果有人能帮助我们找出一种处理错误的最佳方法,我们将不胜感激。谢谢
主要功能:
item.author = req.user._id;
item.description = req.query.description;
item.rating = req.query.rating;
item.save()
.then(result => {
// update user's items
UserController.updateItems(req.user._id, result._id);
ItemController.updateItemRating(req.query.outingId, req.query.rating, res);
res.send(result);
})
.catch(error => {
res.send(error);
});
export const updateItemRating = (itemId, rating, res) => {
Item.findOne({ _id: itemId }).exec((err, item) => {
if (item === undefined || item === null) {
throw new NotFoundError('Item not found; check item ID');
}
Item.findOneAndUpdate(
{ _id: itemId },
{ $set: { rating: rating },
},
(error, item) => {
if (error) {
throw new NotFoundError('Error updating item with new rating');
}
});
});
};
更新配置:
export const updateItemRating = (itemId, rating, res) => {
Item.findOne({ _id: itemId }).exec((err, item) => {
if (item === undefined || item === null) {
return res.status(404).send('Item not found; check item ID');
}
Item.findOneAndUpdate(
{ _id: itemId },
{ $set: { rating: rating },
},
(error, item) => {
if (error) {
res.status(404).send('Error updating item with new rating');
}
});
});
};
更新项目:
export const updateItems = (userId, itemId) => {
User.findOneAndUpdate(
{ _id: userId },
{ $push: { items: [itemId] } },
(err, user) => {
console.log('user' + user);
if (err) {
console.log('got an error in updateItems');
}
});
};
您不应该让更新函数发送结果,而应该抛出()一个错误,这样外部函数将捕获错误,您可以使用它返回错误 考虑这一点的另一种方式是,外部函数使用res.send()处理成功案例,因此它还应该负责错误案例的res.send 数据库层对调用方的了解越少,就越容易重用我们的代码 创建自定义错误类型以封装404:
function NotFoundError(message) {
this.message = (message || "");
}
NotFoundError.prototype = new Error();
然后在你的内在功能中使用它:
item.author = req.user._id;
item.description = req.query.description;
item.rating = req.query.rating;
item.save()
.then(result => {
// update user's items
UserController.updateItems(req.user._id, result._id);
ItemController.updateItemRating(req.query.outingId, req.query.rating, res);
res.send(result);
})
.catch(error => {
res.send(error);
});
export const updateItemRating = (itemId, rating, res) => {
Item.findOne({ _id: itemId }).exec((err, item) => {
if (item === undefined || item === null) {
throw new NotFoundError('Item not found; check item ID');
}
Item.findOneAndUpdate(
{ _id: itemId },
{ $set: { rating: rating },
},
(error, item) => {
if (error) {
throw new NotFoundError('Error updating item with new rating');
}
});
});
};
你的主要目标是:
item.save()
.then(result => {
// update user's items
UserController.updateItems(req.user._id, result._id);
ItemController.updateItemRating(req.query.outingId, req.query.rating, res);
res.send(result);
})
.catch(error => {
if (error instanceof NotFoundError) {
res.status(404).send(error.message);
}
else {
res.send(error);
}
});
您不应该让更新函数发送结果,而应该抛出()一个错误,这样外部函数将捕获错误,您可以使用它返回错误 考虑这一点的另一种方式是,外部函数使用res.send()处理成功案例,因此它还应该负责错误案例的res.send 数据库层对调用方的了解越少,就越容易重用我们的代码 创建自定义错误类型以封装404:
function NotFoundError(message) {
this.message = (message || "");
}
NotFoundError.prototype = new Error();
然后在你的内在功能中使用它:
item.author = req.user._id;
item.description = req.query.description;
item.rating = req.query.rating;
item.save()
.then(result => {
// update user's items
UserController.updateItems(req.user._id, result._id);
ItemController.updateItemRating(req.query.outingId, req.query.rating, res);
res.send(result);
})
.catch(error => {
res.send(error);
});
export const updateItemRating = (itemId, rating, res) => {
Item.findOne({ _id: itemId }).exec((err, item) => {
if (item === undefined || item === null) {
throw new NotFoundError('Item not found; check item ID');
}
Item.findOneAndUpdate(
{ _id: itemId },
{ $set: { rating: rating },
},
(error, item) => {
if (error) {
throw new NotFoundError('Error updating item with new rating');
}
});
});
};
你的主要目标是:
item.save()
.then(result => {
// update user's items
UserController.updateItems(req.user._id, result._id);
ItemController.updateItemRating(req.query.outingId, req.query.rating, res);
res.send(result);
})
.catch(error => {
if (error instanceof NotFoundError) {
res.status(404).send(error.message);
}
else {
res.send(error);
}
});
对
updateItems
和updateItemRating
的函数调用都是异步的。Response send被多次调用,并且不确定首先调用哪个方法send。要解决您的问题,我建议您应用以下技巧:
res.send
,在出现错误或成功情况时,您可以调用相同的回调
UserController.updateItems(请求用户id、结果id、函数(状态、消息){res.status(状态)、send(消息);})代码>
export const updateItemRating = (itemId, rating, callback) => {
Item.findOne({ _id: itemId }).exec((err, item) => {
if (item === undefined || item === null) {
callback(404,'Item not found; check item ID');
}
Item.findOneAndUpdate(
{ _id: itemId },
{ $set: { rating: rating },
},
(error, item) => {
if (error) {
callback(404,'Error updating item with new rating');
}else{
callback(200);
}
});
});
};
对
updateItems
和updateItemRating
的函数调用都是异步的。Response send被多次调用,并且不确定首先调用哪个方法send。要解决您的问题,我建议您应用以下技巧:
res.send
,在出现错误或成功情况时,您可以调用相同的回调
UserController.updateItems(请求用户id、结果id、函数(状态、消息){res.status(状态)、send(消息);})代码>
export const updateItemRating = (itemId, rating, callback) => {
Item.findOne({ _id: itemId }).exec((err, item) => {
if (item === undefined || item === null) {
callback(404,'Item not found; check item ID');
}
Item.findOneAndUpdate(
{ _id: itemId },
{ $set: { rating: rating },
},
(error, item) => {
if (error) {
callback(404,'Error updating item with new rating');
}else{
callback(200);
}
});
});
};
您正试图将
updateItemRating
作为同步函数执行,而这是一个异步函数。你应该连锁承诺,然后在最后只使用一个res.send
。或者使用async/wait,您尝试将updateItemRating
作为同步函数执行,而这是一个异步函数。你应该连锁承诺,然后在最后只使用一个res.send
。或者使用async/Await,我正试图按照您的建议实现,但最终得到一个以Error:Item not found开头的堆栈跟踪;检查项目ID。
捕获来自Mongoose查询的错误是否有问题?我不确定出了什么问题以及为什么我不能正确地捕获错误。我只是注意到我的示例中有一个输入错误-已更新为更正-NotFound.prototype应该是NotFoundError.prototypeYes-我实际上捕获到了这个错误,并在我的应用程序中将其更改为NotFoundError
,但它仍然不起作用。看起来它成功地抛出了错误(因为堆栈跟踪正在被打印),但我从未输入catch语句(console.log
这里没有向console打印任何内容)。我正在尝试按照您的建议实现,但最终得到的堆栈跟踪以error:Item not found;检查项目ID。
捕获来自Mongoose查询的错误是否有问题?我不确定出了什么问题以及为什么我不能正确地捕获错误。我只是注意到我的示例中有一个输入错误-已更新为更正-NotFound.prototype应该是NotFoundError.prototypeYes-我实际上捕获到了这个错误,并在我的应用程序中将其更改为NotFoundError
,但它仍然不起作用。看起来它成功地抛出了错误(因为堆栈跟踪正在打印),但我从未输入catch语句(console.log
这里没有向console打印任何内容)。谢谢!我最终使用了Asyncseries
并按照您的建议应用了回调,现在一切正常了。谢谢!我最终使用了Asyncseries
并按照您的建议应用了回调,现在就可以了。