调用Mongoose文档save()的catch()报undefined错误及响应为null问题
搞定Mongoose save()的catch报错问题
嘿,你的问题根源其实挺明确的,我帮你拆解下:
首先,你现在用的是带回调函数的save()写法,这个版本的save()是不会返回Promise对象的,所以你后面链式调用.catch()的时候,自然就会因为前面的返回值是undefined,抛出"Cannot read property 'catch' of undefined"这个错误。
另外还有个小坑:Mongoose里回调式的save()参数顺序是(error, 保存后的文档),你现在把第一个参数当成了保存后的结果,所以才会打印出null(没报错的时候error就是null)。
下面给你两种修复方案,选你顺手的来:
方案1:和你现有代码风格匹配的Promise链式写法
把save()的回调去掉,直接用Promise的链式调用,这样就能正常用then和catch了:
Script.findById(scriptId) .then(script => { if (script) { const scriptId = script._id.toString(); const demoUrl = `${scriptId}.mydomain.com`; if (true) { // 这里替换成你实际的判断条件就行 script.approved = true; script.demoUrl = demoUrl; // 去掉回调,直接返回save()的Promise return script.save(); } // 处理if条件不满足的情况,返回一个空的resolved Promise return Promise.resolve(null); } // 没找到文档时也返回resolved Promise,避免后续catch误触发 return Promise.resolve(null); }) .then(savedScript => { if (savedScript) { res.json({ message: "Script approved.", demoUrl: `${savedScript._id.toString()}.mydomain.com` }); } else { res.status(404).json({ message: "脚本未找到或未做任何修改" }); } }) .catch(error => { next(error); });
方案2:更简洁的async/await写法
如果你的项目支持ES7的async/await,这种写法可读性更高,不容易踩回调的坑:
// 注意:你的路由处理函数要加上async关键字,比如async (req, res, next) => { ... } try { const script = await Script.findById(scriptId); if (!script) { return res.status(404).json({ message: "脚本未找到" }); } const scriptIdStr = script._id.toString(); const demoUrl = `${scriptIdStr}.mydomain.com`; if (true) { // 替换成你的实际判断逻辑 script.approved = true; script.demoUrl = demoUrl; await script.save(); res.json({ message: "Script approved.", demoUrl: demoUrl }); } else { res.json({ message: "未对脚本做任何修改" }); } } catch (error) { next(error); }
小提醒
- 尽量保持代码风格统一:要么全用回调,要么全用Promise/async-await,混着用很容易出这种奇怪的报错。
- 别忘了处理
script为null的情况,也就是没找到对应文档的场景,避免后续代码出问题。
内容的提问来源于stack exchange,提问作者yasmikash
相关产品推荐
相关产品推荐

