未使用await的异步函数异常:NestJS+Mongoose查询未执行问题
问题描述
我正在开发基于NestJS的Web应用,使用Mongoose作为数据库交互模块。在某接口中执行两个异步数据库查询,但未对其使用await。我的预期是:返回this.roleModel.findByIdAndDelete(id)的Promise,同时this.realmModel.updateMany({}, { $pull: { roles: new Types.ObjectId(id) } })会自行完成解析。
示例代码:
removeRole(id: string | Types.ObjectId) { this.realmModel.updateMany({}, { $pull: { roles: new Types.ObjectId(id) } }); return this.roleModel.findByIdAndDelete(id); }
实际结果却是:返回的Promise已解析,但this.realmModel.updateMany(...)并未执行。若将removeRole声明为async函数,结果符合预期,但我并不关心updateMany的完成时机。我想知道这是NestJS特有的问题,还是JavaScript原生行为?
解答
这不是NestJS特有的问题,属于JavaScript/Node.js的原生行为,核心原因和事件循环、Promise调度以及进程退出时机直接相关:
当你调用
this.realmModel.updateMany()时,它会返回一个Promise,但因为你既没有用await等待它完成,也没有对这个Promise做任何后续处理(比如绑定.catch()捕获错误),Node.js的事件循环可能在这个异步数据库请求被调度执行前,就因为当前同步代码执行完毕、没有其他挂起的任务而提前终止。尤其是在HTTP请求处理结束后,如果没有未解决的Promise或其他异步任务,Node.js进程会快速退出,导致updateMany的数据库操作被中断,根本没机会执行。当把
removeRole声明为async函数后,即使你没有awaitupdateMany,async函数本身会返回一个Promise。这个Promise会让Node.js保持事件循环运行,直到函数内部所有同步代码执行完毕,给updateMany足够的时间完成数据库请求,所以操作能正常执行。补充:Mongoose内部的部分异步操作,在没有被
await或监听其Promise状态的情况下,可能会因为内部的懒加载逻辑或未处理Promise拒绝的抑制机制,导致操作没有被真正触发,但这只是次要因素,核心还是Node.js事件循环的退出时机问题。
建议方案
即使你不关心updateMany的执行结果,也应该至少处理它的Promise,避免未处理的错误和操作被中断。比如用catch捕获错误:
removeRole(id: string | Types.ObjectId) { this.realmModel.updateMany({}, { $pull: { roles: new Types.ObjectId(id) } }) .catch(err => console.error('更新Realm角色关联失败:', err)); return this.roleModel.findByIdAndDelete(id); }
如果是NestJS项目,推荐使用框架自带的Logger模块来记录错误,更符合项目规范。
内容的提问来源于stack exchange,提问作者Andy95

