async函数then块无法获取正确返回值?Mongoose操作MongoDB问题
问题:addQuestion函数返回undefined的原因及解决办法
你使用mongoose向mongodb添加文档时,日志显示addQuestion中的q.save()执行成功并打印了新增文档,但调用它的addQuestionHandler的then块中获取到的返回值为undefined。相关代码及日志如下:
相关代码
addQuestion函数
async function addQuestion (description,hints,topic) { var q = null; dotenv.config(); console.log(`adding question:`); console.log(`description: ${description}`); console.log(`hints: ${hints}`); console.log(`topic: ${topic}`); const Question = mongoose.model(topic, questionSchema,topic); q = Question({ description: description, hints: hints, topic: topic }); await q.save() .then((result) => { console.log(`added question ${result}`); return result; }) .catch ( (err)=>{ console.log(`error in adding question: ${err}`); return null; }); }
addQuestionHandler函数
addQuestionHandler: async function (req, res) { console.log(`adding question: request is ${req}`); await addQuestion(req.description, req.hints,req.topic) .then((question)=>{ console.log(`added question ${question}`); console.log(`returning value ${question}`); return question; }) .catch((error) => { console.log(`error in adding question: ${error}`); }) }
成功日志
added question { description: 'description of question on area', hints: [ 'area hint 1', 'area hint 2' ], topic: 'areas', _id: new ObjectId("64f47a56e5b349ec88a8ca98"), __v: 0 }
原因分析
addQuestion是async函数,但它没有显式返回值。虽然你在q.save().then()里return了result、catch里return了null,但这些return仅在对应的回调函数内生效,并没有作为整个addQuestion函数的返回值向外传递。async函数如果没有显式return,默认返回undefined,所以addQuestionHandler中await该函数后拿到的就是undefined。
修复方案
方案1:返回Promise链
直接return整个q.save()的Promise链,让async函数把这个Promise的最终结果作为自身返回值:
async function addQuestion (description,hints,topic) { dotenv.config(); console.log(`adding question:`); console.log(`description: ${description}`); console.log(`hints: ${hints}`); console.log(`topic: ${topic}`); const Question = mongoose.model(topic, questionSchema,topic); const q = Question({ description: description, hints: hints, topic: topic }); // 返回整个Promise链 return q.save() .then((result) => { console.log(`added question ${result}`); return result; }) .catch ( (err)=>{ console.log(`error in adding question: ${err}`); return null; }); }
方案2:改用纯async/await写法(更推荐)
避免混用then/catch和await,代码逻辑更清晰:
async function addQuestion (description,hints,topic) { dotenv.config(); console.log(`adding question:`); console.log(`description: ${description}`); console.log(`hints: ${hints}`); console.log(`topic: ${topic}`); const Question = mongoose.model(topic, questionSchema,topic); const q = Question({ description: description, hints: hints, topic: topic }); try { const result = await q.save(); console.log(`added question ${result}`); return result; } catch (err) { console.log(`error in adding question: ${err}`); return null; } }
内容的提问来源于stack exchange,提问作者Manu Chadha
相关产品推荐
相关产品推荐

