为何User.findOne的then回调中userid关联值为undefined?执行顺序解惑
问题分析与解决方案
嗨,这个问题其实是异步流程混用了回调和Promise导致的顺序混乱,我来给你拆解清楚:
核心原因
你写的User.findOne传入了回调函数,这时候Mongoose的这个方法就不会返回Promise了!后面的.then()会直接被调用,完全不等数据库查询完成。
数据库查询是异步操作,回调里的console.log(userid)(你的标记(1))会在主线程处理完同步代码后才执行;而.then里的代码(标记(2))是紧接着findOne调用就执行的,所以此时userid还没被赋值,newCharacter.character.author自然就是undefined。
修复方案
我们需要统一用Promise风格(或者async/await)来处理异步流程,保证代码按预期顺序执行:
方案1:纯Promise链式调用
User.findOne({'user.id': author.id}, 'id') .then(userid => { console.log(userid); // 现在这部分会先执行 newCharacter.character.author = userid; console.log('does it work? '+newCharacter.character.author); // 接着执行save操作,继续链式调用 return newCharacter.save(); }) .then(character => { console.log('Success! ' + character.id); }) .catch(err => { // 别忘了处理可能出现的错误 console.error('出错了:', err); });
方案2:用async/await让代码更易读
如果你的运行环境支持ES2017+,async/await会让异步代码看起来像同步代码,更直观:
async function createNewCharacter() { try { // 等待查询完成,拿到userid const userid = await User.findOne({'user.id': author.id}, 'id'); console.log(userid); newCharacter.character.author = userid; console.log('does it work? '+newCharacter.character.author); // 等待保存完成 const character = await newCharacter.save(); console.log('Success! ' + character.id); } catch (err) { console.error('操作失败:', err); } } // 调用这个异步函数 createNewCharacter();
关键知识点
Mongoose的所有查询方法都支持两种模式:
- 传入回调函数:直接在回调里处理结果,不返回Promise
- 不传入回调:返回一个Promise对象,你可以用
.then()或者await来处理异步结果
之前的错误就是同时用了回调和Promise,导致异步流程的控制完全失效~
内容的提问来源于stack exchange,提问作者Telion
相关产品推荐
相关产品推荐

