I am trying to query, that would get all of the earning and withdrawal amount and sum, but somehow after the forEach loop is done and exits, all of the updated values I placed in a variable return to their original values.
var withdrawbalance = 0;
var totalearning = 0;
userplans.forEach((up) => {
DepositEarning.findOne({deposit: up.deposit._id})
.then(depositearning => {
withdrawbalance += parseInt(depositearning.WithdrawableBalance, 10);
});
Earning.findOne({deposit: up.deposit._id})
.then(earnings => {
totalearning += parseInt(earnings.Earning, 10);
});
})
console.log(withdrawbalance);
console.log(totalearning);
答案 0 :(得分:4)
您正在forEach
中运行异步代码,并且forEach
不会等到异步代码完成,为此,必须用等待的原语包装异步代码,像这样
await Promise.all(userplans.map(async (up) => {
await DepositEarning.findOne({deposit: up.deposit._id})
.then(depositearning => {
withdrawbalance += parseInt(depositearning.WithdrawableBalance, 10);
});
await Earning.findOne({deposit: up.deposit._id})
.then(earnings => {
totalearning += parseInt(earnings.Earning, 10);
});
}))
答案 1 :(得分:0)
我认为原因可能是DepositEarning.findOne()和Earning.findOne()都是异步函数。这意味着它们不会立即返回值,因此循环后您的变量仍然相同。
答案 2 :(得分:0)
这里是一种实用的方法,可消除循环内部的突变副作用。为此,您需要一个支持Object Rest传播的引擎:
async function calculate(userplans) {
const add = (acc, n) => acc + n;
const flatten = (acc, e) => ({
depositEarnings: [...acc.depositEarnings, e.depositEarnings],
earnings: [...acc.earnings, e.earnings]
});
const {depositEarnings, earnings} = (await Promise.all(userplans
.map(async (up) => ({
depositEarnings: await DepositEarning.findOne({deposit: up.deposit._id}),
earnings: await Earning.findOne({deposit: up.deposit._id})
}))))
.reduce(flatten, {depositEarnings: [], earnings: []});
const withdrawalBalance = depositEarnings
.map(d => parseInt(d.WithdrawableBalance, 10))
.reduce(add, 0);
const totalEarning = earnings
.map(e => parseInt(e.Earning, 10))
.reduce(add, 0);
console.log(withdrawalBalance);
console.log(totalEarning);
}
答案 3 :(得分:0)
只需加上我的两分钱,
正如其他答案所述,您的foreach
循环正在使用异步代码。它正在使用不属于Js的某些API。
将调用推送到调用堆栈,然后将其从调用堆栈中删除。因为现在该工作将由API处理。呼叫
console.log(withdrawbalance);
console.log(totalearning);
被添加到调用堆栈中,现在的值是什么? 0 0。
API完成工作后,将在task queue
中添加函数,然后event loop
将检查调用堆栈是否为空。由于现在为空,因此将函数添加到调用堆栈中。
然后运行。然后您将获得withdrawbalance and
totalearning
值的真实值。
答案 4 :(得分:-1)
forEach
is asynchronous. So the console.log runs before your mutation loop. You can make it synchronous by using map
, but even then - you have asynchronous calls inside it. You will need to flatten it further - probably by doing Promise.all on a map, then reducing the output of that.