为什么forEach循环内的Mongoose findById查询无法更新外部sum变量
问题根因
你遇到的问题本质是Node.js 异步 IO 执行顺序导致的,和变量作用域无关,具体可以拆解为以下几点:
- 你调用的
Product.findById是异步方法,传入的回调函数不会立刻执行,会被放到异步任务队列,等当前主线程的同步代码全部执行完成后才会被调度执行 - 你写的
forEach遍历本身是同步执行的,它会一口气把所有findById请求发出去,然后立刻就执行后面的console.log(sum),这个时候所有的数据库查询回调都还没被触发,sum 的值还是初始的 0,所以你看到的输出就是 0 - 等后面所有数据库查询结果返回、回调函数依次执行的时候,sum 确实会被累加为正确的总和,但这个时候你之前的打印操作早就执行完了,自然看不到更新后的值
可参考的修正写法
如果要实现你的需求,可以把异步回调改为async/await的写法,避免回调嵌套的执行顺序问题:
module.exports.checkoutOrder = async (reqBody, buyerId, isAdmin) => { let sum = 0; // 用for...of遍历支持在内部用await等待异步任务完成 for (const item of reqBody.items) { const result = await Product.findById(item.productId); sum += result.price; } console.log(sum); // 后续可以继续处理sum相关逻辑 }
如果想提升查询效率,也可以一次性查询所有商品ID再求和,不需要循环发请求:
module.exports.checkoutOrder = async (reqBody, buyerId, isAdmin) => { // 提取所有商品ID const productIds = reqBody.items.map(item => item.productId); // 一次性查询所有符合条件的商品 const products = await Product.find({ _id: { $in: productIds } }); // 累加价格 const sum = products.reduce((acc, cur) => acc + cur.price, 0); console.log(sum); }
内容的提问来源于stack exchange,提问作者quielfala
相关产品推荐
相关产品推荐

