为何Mongoose预钩子无法配合箭头函数语法使用?
为什么Mongoose的remove预钩子用箭头函数不生效?
这个问题我之前踩过坑!核心原因就是箭头函数的this指向特性和Mongoose钩子的工作机制不兼容。
你看,Mongoose的预钩子(pre hook)是靠this来指向当前正在操作的文档实例的,但箭头函数不会绑定自己的this,它会直接继承外层作用域的this——这就导致你代码里的this._id根本取不到要删除的Post文档ID,后续删除Comment、更新User的操作自然找不到匹配的文档,看起来就像钩子完全没执行一样。
先还原你出问题的代码:
PostSchema.pre("remove", async () => { await Comment.remove({ _postId: this._id }).exec(); await User.update({ $pull: { _posts: this._id } }).exec(); });
这里箭头函数里的this根本不是当前的Post文档,而是外层作用域的this(在Node环境里可能是global,严格模式下甚至是undefined),所以this._id是undefined,数据库操作等于白跑一趟。
解决方法很简单,把箭头函数换成普通函数就行,Mongoose会自动把当前要删除的文档绑定到函数的this上:
PostSchema.pre("remove", async function() { // 现在this就是当前要删除的Post文档啦 await Comment.deleteMany({ _postId: this._id }); await User.updateMany({}, { $pull: { _posts: this._id } }); });
顺便提两个小建议:
- Mongoose现在已经不推荐用
remove()和update()这些旧方法了,建议换成deleteMany()(批量删除)和updateMany()(批量更新),语义更清晰; - 也可以不用加
.exec(),因为async/await已经能直接处理Mongoose的Query对象了。
只要把箭头函数换成普通函数,你的关联数据清理逻辑就能正常工作啦!
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

