javascript - 为什么 findOneAndRemove 有时会在回调中将 null 传递给 doc?
问题描述
我正在使用以下应该具有回调输入的函数: https ://mongoosejs.com/docs/api.html#model_Model.findOneAndRemove
我有以下 Mutation 对象,该对象应该从数据库中删除特定药物,然后从包含该 ID 的所有 Day 条目的数组中删除其 MedicineId 的所有实例。
deleteMedicine: {
type: MedicineType,
args: {
id: { type: new GraphQLNonNull(GraphQLID) }
},
async resolve (parent, args) {
let res = Medicine.findOneAndRemove({ _id: args.id }, async (err, doc) => {
if (err === null && doc === null || doc === null) {
return;
} else if (err) {
console.error(err);
return;
} else {
return await Promise.all(doc.dayNames.map(dayName => {
return DayOfWeek.findByIdAndUpdate(dayName, { $pull: { medicineIds: doc._id }})
.catch((error1) => console.error(error1));
})).catch((error2) => console.error(error2));
}
});
await res;
return res;
}
}
findOneAndRemove 成功删除了 Medicine 集合中具有 args.id 的文档,但是当它调用回调函数时,有时会将 null 传递给 doc,因此回调函数无法始终正确执行。
即使我发现了所有错误,我也会收到未处理的错误警告。\
根据这篇文章,我添加了当 err 和 doc 都为空时处理的逻辑: https ://github.com/Automattic/mongoose/issues/5022
解决方案
你应该只对 GraphQL.js 使用 Promises,而不是回调。如果您使用的库不支持 Promise,那么您需要将每个回调包装在 Promise中。但是,mongoose
它有很好的 Promise 支持——您只需从方法调用中省略回调,调用将返回一个 Promise。
为了避免在使用 Promises 时出现“回调地狱”以及正确链接 Promises 的问题,通常最好使用 async/await 语法。您清理后的解析器看起来像:
async resolve (parent, args) {
// Omit the callback to get a Promise and then await the result
const medicine = await Medicine.findOneAndRemove({ _id: args.id })
// If a medicine with that ID couldn't be found, we'll get a null
if (medicine) {
// Make sure we await the Promise returned by Promise.all
await Promise.all(doc.dayNames.map(dayName => DayOfWeek.findByIdAndUpdate(
dayName,
{ $pull: { medicineIds: doc._id } }
))
}
// Make sure we return the appropriate result depending on the field's type
return medicine
}
通常在处理 Promises 时,我们使用该catch
方法(或 try/catch 与 async/await)来处理错误。但是,如果您想屏蔽或以其他方式格式化您的错误,这仅在解析器中是必需的——否则,GraphQL 会很乐意为您捕获任何错误并在响应中返回它们。但是,这仅在您的 Promise 正确链接并且解析器返回 Promise 时才有效。如果你最终得到一个没有等待的“孤儿” Promise,你会看到未处理的错误警告。
推荐阅读
- fix-protocol - 如何为每个会话设置不同的“ResetOnLogon”?
- php - Woocommerce 将属性添加到特定的 Hook
- amazon-web-services - AWS Cloud Formation 在创建之前删除资源
- python - Django API:如何保存/另存为项目?
- java - Python 到 Java 代码:Java 中的 String.encode()
- java - getUserPrincipal() 是如何工作的?我应该什么时候使用它?
- javascript - ReactJS 页面转换
- php - PHP file_get_contents 在我的服务器上被阻止
- php - Elasticsearch - 使用部分单词对单词匹配进行评分
- python - 发布字典列表并更新或创建