nodejs 中的异步等待 mongodb 查询不起作用
Async await in nodejs for mongodb query not working
我有以下架构
const schema = new Schema(
{
ImageId: { type: String, ref: models.IMAGES },
reportedBy:[
userId:{type:String, ref: models.USER}
]
}
);
class ImageReport {}
schema.loadClass(ImageReport);
module.exports = model(models.IMAGEREPORT, schema);
以及以下代码
reportImage: async (req, res, next) => {
try {
const { ImageId } = req.params;
const image = await Image.findOne({ ImageId }); // there is an image schema with fields: ImageId and url
if(!image)
return res.status(400).send({
statusCode: 400,
error:"CANNOT FIND THE IMAGE",
data: {},
});
const userId = "some userId";
try{
let imageReports = await ImageReport.findOne({ ImageId:ImageId})
if(imageReports){
imageReports.reportedBy.forEach(rep=>{
if(rep.userId===userId)
// this error should be returned immediately. Instead it goes to ImageReport.updateOne() call
return res.status(400).send({
statusCode: 400,
error: "YOU HAVE ALREADY REPORTED THIS IMAGE",
data: {},
});
});
}
} catch(err){
return res.status(400).send({
statusCode: 400,
error: error,
data: {},
});;
}
// this is called even if the error is found in the above try catch block
await ImageReport.updateOne(
{ImageId:ImageId},
{
$push:{
reportedBy:userId
}
},
{upsert:true},
function (error) {
if (error) {
return res.status(400).send({
statusCode: 400,
error: error,
data: {},
});
}
}
)
return res.status(200).send({
statusCode: 200,
error: 'THE IMAGE WAS REPORTED SUCCESSFULLY',
data: {},
});
} catch (e) {
return res.status(400).send({
statusCode: 400,
error: error,
data: {},
});
}
},
当我 运行 此查询并假设用户已经报告了图像(即,他们的用户 ID 在 'reportedBy' 数组中)时 API 调用不会 return错误尽快。相反,它转到 ImageReport.updateOne() 调用并插入文档,然后 return 出现错误消息(“您已经报告了此图像”)
谁能告诉我为什么 async await 不能正常工作?我也遇到以下错误
Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on
unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:16920) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
使用 for of
而不是 forEach
方法,因为您的 return
刚刚完成了 forEach
:
中某个迭代的回调
for (const rep of imageReports.reportedBy) {
if(rep.userId===userId)
// this error should be returned immediately. Instead it goes to ImageReport.updateOne() call
return res.status(400).send({
statusCode: 400,
error: "YOU HAVE ALREADY REPORTED THIS IMAGE",
data: {},
});
}
我认为这是一个重构案例。当然会返回错误 400,但它只会停止插入错误的范围。请注意,此错误是在第二次捕获时发送的,但第一个(更新)的范围仍然存在。
由于 JS 的范围很棘手,我会做一些更改来尝试避免这种行为:
- 拆分函数 - 在调用的不同函数中插入和更新逻辑(使用 await)。例如:
findProcessedImageReport: async (params) => {
// ...
if(imageReports){
imageReports.reportedBy.forEach(rep=>{
if(rep.userId===userId)
throw new Error("YOU HAVE ALREADY REPORTED THIS IMAGE");
});
}
// ... not error
return imageReportData;
}
updateReportImage: params => { // ... logic }
- 在调用此函数时处理一次错误。在函数本身中,我会抛出错误而不是直接响应它来表达。所以,我会在明确响应的地方得到抛出的错误。
reportImage: async () => {
try {
const processedImageReport = await findProcessedImageReport(params)
// The current flow would be stopped if got error "error: "YOU HAVE ALREADY REPORTED THIS IMAGE"
await processUpdateImageReport(params)
return res.status(200).json({success: true, ...data})
} catch (err){
return res.status(400).json(err)
}
}
我有以下架构
const schema = new Schema(
{
ImageId: { type: String, ref: models.IMAGES },
reportedBy:[
userId:{type:String, ref: models.USER}
]
}
);
class ImageReport {}
schema.loadClass(ImageReport);
module.exports = model(models.IMAGEREPORT, schema);
以及以下代码
reportImage: async (req, res, next) => {
try {
const { ImageId } = req.params;
const image = await Image.findOne({ ImageId }); // there is an image schema with fields: ImageId and url
if(!image)
return res.status(400).send({
statusCode: 400,
error:"CANNOT FIND THE IMAGE",
data: {},
});
const userId = "some userId";
try{
let imageReports = await ImageReport.findOne({ ImageId:ImageId})
if(imageReports){
imageReports.reportedBy.forEach(rep=>{
if(rep.userId===userId)
// this error should be returned immediately. Instead it goes to ImageReport.updateOne() call
return res.status(400).send({
statusCode: 400,
error: "YOU HAVE ALREADY REPORTED THIS IMAGE",
data: {},
});
});
}
} catch(err){
return res.status(400).send({
statusCode: 400,
error: error,
data: {},
});;
}
// this is called even if the error is found in the above try catch block
await ImageReport.updateOne(
{ImageId:ImageId},
{
$push:{
reportedBy:userId
}
},
{upsert:true},
function (error) {
if (error) {
return res.status(400).send({
statusCode: 400,
error: error,
data: {},
});
}
}
)
return res.status(200).send({
statusCode: 200,
error: 'THE IMAGE WAS REPORTED SUCCESSFULLY',
data: {},
});
} catch (e) {
return res.status(400).send({
statusCode: 400,
error: error,
data: {},
});
}
},
当我 运行 此查询并假设用户已经报告了图像(即,他们的用户 ID 在 'reportedBy' 数组中)时 API 调用不会 return错误尽快。相反,它转到 ImageReport.updateOne() 调用并插入文档,然后 return 出现错误消息(“您已经报告了此图像”)
谁能告诉我为什么 async await 不能正常工作?我也遇到以下错误
Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on
unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:16920) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
使用 for of
而不是 forEach
方法,因为您的 return
刚刚完成了 forEach
:
for (const rep of imageReports.reportedBy) {
if(rep.userId===userId)
// this error should be returned immediately. Instead it goes to ImageReport.updateOne() call
return res.status(400).send({
statusCode: 400,
error: "YOU HAVE ALREADY REPORTED THIS IMAGE",
data: {},
});
}
我认为这是一个重构案例。当然会返回错误 400,但它只会停止插入错误的范围。请注意,此错误是在第二次捕获时发送的,但第一个(更新)的范围仍然存在。
由于 JS 的范围很棘手,我会做一些更改来尝试避免这种行为:
- 拆分函数 - 在调用的不同函数中插入和更新逻辑(使用 await)。例如:
findProcessedImageReport: async (params) => {
// ...
if(imageReports){
imageReports.reportedBy.forEach(rep=>{
if(rep.userId===userId)
throw new Error("YOU HAVE ALREADY REPORTED THIS IMAGE");
});
}
// ... not error
return imageReportData;
}
updateReportImage: params => { // ... logic }
- 在调用此函数时处理一次错误。在函数本身中,我会抛出错误而不是直接响应它来表达。所以,我会在明确响应的地方得到抛出的错误。
reportImage: async () => {
try {
const processedImageReport = await findProcessedImageReport(params)
// The current flow would be stopped if got error "error: "YOU HAVE ALREADY REPORTED THIS IMAGE"
await processUpdateImageReport(params)
return res.status(200).json({success: true, ...data})
} catch (err){
return res.status(400).json(err)
}
}