为何调用push后数组仍为空?MongoDB异步查询引发的问题
问题分析
你碰到的核心问题其实是异步操作的执行顺序,和作用域关系不大哦。User.findById()是异步方法——它的回调函数要等数据库查询完成后才会触发,但forEach是同步遍历数组的方法。当你执行到console.log(users)时,所有findById的回调都还没来得及执行,users数组自然还是空的。
解决方案1:用async/await + Promise.all(推荐)
这是最直观清晰的写法,先把每个异步查询转换成Promise,再用Promise.all等待所有查询完成:
const usersList = camp.usersList; // 把每个findById调用包装成Promise const userPromises = usersList.map(userId => { return User.findById(userId).catch(err => { console.error(err); res.redirect('/admin/db'); throw err; // 抛出错误让Promise.all能感知到异常 }); }); // 这段代码要放在async函数里,因为用到了await try { const users = await Promise.all(userPromises); console.log(users); // 这里就能得到预期的[user1, user2, ...] // 接下来可以用users做后续业务处理 } catch (err) { res.redirect('/admin/db'); }
解决方案2:Promise链式调用(兼容旧环境)
如果你的运行环境不支持async/await,可以用Promise.all结合then来处理:
const usersList = camp.usersList; const userPromises = usersList.map(userId => { return User.findById(userId).catch(err => { console.error(err); res.redirect('/admin/db'); throw err; }); }); Promise.all(userPromises) .then(users => { console.log(users); // 这里就是填充完成的用户数组 // 后续操作写在这里 }) .catch(err => { res.redirect('/admin/db'); });
再给你理清楚原代码的执行顺序
- 初始化
users为空数组 - 执行
usersList.forEach,遍历每个userId,立即触发User.findById(但数据库查询是异步的,回调还没执行) - 遍历完成后,立刻执行
console.log(users),此时所有findById的回调都还没跑,所以输出空数组 - 过一会儿数据库查询陆续完成,回调函数才开始执行,把user push到
users里,但这时候console.log早就执行完了
内容的提问来源于stack exchange,提问作者user11075555
相关产品推荐
相关产品推荐

