Mongoose中await save未生效,appeal为何出现undefined报错?
问题描述
我有两台服务器,其中一台运行正常,但另一台(基于第一台修改而来)出现问题。
以下代码无法正常运行:
router.post("/", async (req, res, next) => { const newBriefAppeal = await new BriefAppeal(req.body); let appealId; let target; let goals; let brand; let ***; try { const savedBriefAppeal = await newBriefAppeal.save(function (err, appeal) { appealId = appeal.id; target = appeal.step01target; goals = appeal.step02goals; brand = appeal.step03brand; *** = appeal.*** }); res.status(200).json(savedBriefAppeal); } catch (err) { res.status(500).json(err); } });
报错信息如下:
node:events:491 throw er; // Unhandled 'error' event ^ TypeError: Cannot read properties of undefined (reading 'id')
但类似项目中的如下代码运行正常:
router.post("/", async (req, res, next) => { const newAppeal = await new Appeal(req.body); let appealId; let name; let email; let phone; let subject; let message; let attachments = []; try { const savedAppeal = await newAppeal.save(function (err, appeal) { appealId = appeal.id; name = appeal.name; email = appeal.email; phone = appeal.phone; subject = appeal.subject; message = appeal.text; attachments = appeal.appealAttach.map((attachment) => ({ filename: attachment, path: "./uploads/media/mailAttachments/" + attachment, })); }); res.status(200).json(savedAppeal); } catch (err) { res.status(500).json(err); } });
请问我哪里出错了,为什么appeal会是undefined?
问题分析与解决
核心问题:混用await与回调函数
你同时使用了await(异步等待模式)和回调函数两种异步处理方式,这是导致appeal为undefined的直接原因。
当用await调用save()时,Mongoose会直接返回保存后的文档对象,此时回调函数的参数逻辑会被完全打乱——Mongoose不会再向回调函数传入正确的appeal实例,甚至会因为异步流程冲突,导致回调里的appeal变为undefined。
另外补充:new BriefAppeal(req.body)是同步创建模型实例的操作,不需要加await,多余的await也可能引发隐性的异步流程问题。
修正后的代码
统一使用await模式,去掉冗余的回调函数:
router.post("/", async (req, res, next) => { // 创建实例是同步操作,无需await const newBriefAppeal = new BriefAppeal(req.body); let appealId; let target; let goals; let brand; let ***; try { // 直接用await获取保存后的文档 const savedBriefAppeal = await newBriefAppeal.save(); // 从savedBriefAppeal中提取所需字段 appealId = savedBriefAppeal.id; target = savedBriefAppeal.step01target; goals = savedBriefAppeal.step02goals; brand = savedBriefAppeal.step03brand; *** = savedBriefAppeal.***; res.status(200).json(savedBriefAppeal); } catch (err) { res.status(500).json(err); } });
为什么另一台服务器/项目的代码能运行?
这属于Mongoose版本兼容性的“巧合”:旧版本Mongoose对这种混用模式的容错性较高,没有严格限制异步流程的冲突,但这属于未定义行为——官方并不推荐这种写法,随时可能在版本升级或环境变化时失效。
内容的提问来源于stack exchange,提问作者Mithra
相关产品推荐
相关产品推荐

