我正在通过数组中的 _id 查找文档。然后,我更改“余额”字段并保存文档。该操作执行了五次,但余额仅更改了一次。代码:
users.forEach(async(user) => {
if (user.active) {
/* SOME STUFF */
const owner = await Owner.findById(user.owner)
owner.balance = (owner.balance * 100 - 0.01 * 100) / 100
await owner.save()
}
})
尝试过:
Owner.findById(user.owner).then((owner) => {
owner.balance = (owner.balance * 100 - 0.01 * 100) / 100
owner.save(err => {
if(err) console.log(err)
})
})
也尝试过:
owner.markModified(balance);
所有者架构:
const ownerSchema = new Schema({
balance: {
type: Number
}
});
Test output from console 在此图片上,您可以看到测试输出。之前的余额为99.53。 因此,余额应为99.48,但应为99.52。
答案 0 :(得分:0)
为什么不尝试
Owner.findByIdAndUpdate()
它将通过ID查找所有者并更新它,从而缩短并改善了代码的版本(简洁)
答案 1 :(得分:0)
您可能期望在forEach()中一个一个地处理每个用户,但是这不会发生,而是宁愿同时运行。
要使代码运行才能执行的操作是使用for ... of,这将确保执行顺序。如下所示:
for(let user of users) {
if (user.active) {
/* SOME STUFF */
const owner = await Owner.findById(user.owner)
owner.balance = (owner.balance * 100 - 0.01 * 100) / 100
await owner.save()
}
}
答案 2 :(得分:0)
问题出在您使用forEach函数上。
当您在函数的前面编写async
时,您基本上将其包装为一个Promise,这意味着它的返回值被更改为一个Promise。
forEach没有返回值,这意味着当您将其包装为一个承诺时,没有人正在等待该承诺,这会导致意外的行为。并且您的情况实际上确实更新了5次,但并不像您期望的那样同步。
我建议使用bluebird之类的库,因为它具有强大的功能,代码如下所示:
let Promise = require("bluebird")
....
let users = [user array];
await Promise.mapSeries(users, (user) => {
if (user.active) {
/* SOME STUFF */
const owner = await Owner.findById(user.owner)
owner.balance = (owner.balance * 100 - 0.01 * 100) / 100
await owner.save()
}
})
它现在可以根据需要运行。