You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:40:24