简体   繁体   English

在javascript中的promise-aware for循环中更新对象属性时出现问题

[英]Problem updating object properties inside a promise-aware for loop in javascript

I am having a problem accessing updated object properties inside a for loop in Javascript.我在 Javascript 的 for 循环中访问更新的对象属性时遇到问题。

let distribution = await ctx.db.query.distribution(
      {
        where: {
          id,
        },
      },
      `
    {
      id
      clients {
        id
        wallet {
          amount
        }
      }
    }`,
  );

let count = 0;

for (const client of distribution.clients) {
   await ctx.db.mutation.updateWallet({
       where: {
         id: client.id,
       },
       data: {
         amount: client.wallet.amount + someAmount,
       },
    });
    distribution.clients[count].wallet.amount = client.wallet.amount + someAmount;
    count++;
  }

In the above code, I execute a graphQL query to fetch all information associated with a distribution.在上面的代码中,我执行了一个 graphQL 查询来获取与分布相关的所有信息。 I then want to iterate through the associated clients array and update each client's wallet.然后我想遍历关联的客户端数组并更新每个客户端的钱包。 The same client may appear multiple times in this array and each time their wallet must be updated.同一个客户端可能在这个数组中出现多次,每次都必须更新他们的钱包。

A problem occurs when a wallet has already been updated in a previous iteration.当钱包在上一次迭代中已经更新时,就会出现问题。 When I try to update the amount a second time, the client.wallet.amount reflects the initial value of the wallet rather than value after the first update.当我尝试第二次更新金额时,client.wallet.amount 反映的是钱包的初始值,而不是第一次更新后的值。

Clearly the property clients[count].wallet.amount attribute of the distribution object isn't being updated after each iteration.显然,分发对象的属性 clients[count].wallet.amount 不会在每次迭代后更新。 I thought javascript objects were passed by reference, and therefore the object should be updated after each iteration.我认为 javascript 对象是通过引用传递的,因此应该在每次迭代后更新对象。

Could someone explain to me why the distribution object property is not being updated and how I can update it correctly?有人可以向我解释为什么分发对象属性没有被更新以及我如何正确更新它?

FYI: I cannot use other loops such as forEach as it is not promise-aware and does not suppose async/await仅供参考:我不能使用其他循环,如 forEach,因为它不是承诺感知的,也不假设 async/await

A problem occurs when a wallet has already been updated in a previous iteration.当钱包在上一次迭代中已经更新时,就会出现问题。

Each wallet object is only modified once when the loop runs.每个钱包对象在循环运行时只修改一次。 Two or more wallet objects in the array may represent the same row in the database, but they are still distinct objects -- changing one will not change the other.数组中的两个或多个钱包对象可能代表数据库中的同一行,但它们仍然是不同的对象——改变一个不会改变另一个。

const wallets = [
  { id: 1, amount: 0 },
  { id: 2, amount: 0 },
  { id: 1, amount: 0 },
]
for (const wallet of wallets) {
  wallet.amount = wallet.amount + 5
}
console.log(wallets[0]) // { id: 1, amount: 5 }
console.log(wallets[1]) // { id: 2, amount: 5 }
console.log(wallets[2]) // { id: 1, amount: 5 }

Note that we don't need to use a count variable at all.请注意,我们根本不需要使用count变量。 Because the const wallet is a reference to the original object in the array, if we modify it, we modify the original object.因为const wallet是对数组中原始对象的引用,如果我们修改它,就是修改原始对象。

If you want need to track the amounts by ID, you'd need to implement that logic.如果您需要按 ID 跟踪金额,则需要实现该逻辑。 For example:例如:

const wallets = [
  { id: 1, amount: 0 },
  { id: 2, amount: 0 },
  { id: 1, amount: 0 },
]
const amountsById = {}
for (const wallet of wallets) {
  amountsById[wallet.id] = (amountsById[wallet.id] || wallet.amount) + 5
}
const updatedWallets = wallets.map(wallet => ({
  ...wallet,
  amount: amountsById[wallet.id],
}))
console.log(updatedWallets[0]) // { id: 1, amount: 10 }
console.log(updatedWallets[1]) // { id: 2, amount: 5 }
console.log(updatedWallets[2]) // { id: 1, amount: 10 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM