0

下面的循环调用一个异步函数,这里是使用 web3 的智能合约交互。我想通过调用 balanceOf() 来获取令牌数组的余额,然后使用附加的 usdrate 将其转换。对于并行处理,我使用 Promise.all。显然,Promise.all() 下的具有访问权限 [I % currency.length] 的函数不起作用,因为无法保证排序结果。

我的问题是,我怎样才能将金额与附加到代币的正确 usdrate 相乘并仍然使用 Promise.all?

currencies = [{
    contract: token1,
    usdrate: 0.5
  },
  {
    contract: token2,
    usdrate: 1.0
  },
  {
    contract: token3,
    usdrate: 1.05
  },
  {
    contract: token4,
    usdrate: 1.10
  },
  {
    contract: token5,
    usdrate: 1.40
  },
  {
    contract: token6,
    usdrate: 1.0
  },
  {
    contract: token7,
    usdrate: 1.0
  }
];
}

async function getUsdWealthAsync(addresses) {
  var totalWealth = 0;
  var amountPromises = [];
  for (var j = 0; j < currencies.length; j++) {
    for (var i = 0; i < addresses.length; i++) {
      amountPromises.push(currencies[j].contract.methods.balanceOf(addresses[i]).call());
    }
  }
  await Promise.all(amountPromises).then(function(amounts) {
    for (var i = 0; i < amounts.length; i++) {
      amounts[i] = Number.parseInt(amounts[i]);
      totalWealth += (amounts[i] / 100) * currencies[i % currencies.length].usdrate;
    }
  })
  return totalWealth;
}

4

3 回答 3

2

async函数总是返回 a Promise,你可以定义一个异步函数来接收地址和货币并返回Promise已经完成计算的 a ,这样你就不会遇到索引问题。就像是


async function getAmount(currency, address) {
   const amount = await currency.contract.methods.balanceOf(address).call();
   return amount * currency.usdrate;
}


async function getUsdWealthAsync(addresses) {
  const amountPromises = [];
  for (const currency of currencies) {
    for (const address of addresses) {
      amountPromises.push(getAmount(currency,address)/*Remember, calling this funciton returns a Promise*/);
    }
  }
  const realAmounts = await Promise.all(amountPromises)
  return realAmounts.reduce((total,current) => total+current, 0);
}


通话的最后一行reduce应该是您拥有的所有金额的总和

于 2022-01-24T19:37:30.833 回答
1

为什么不使用嵌套Promise.all()将特定货币的所有异步调用捆绑在单个 Promise 下?通过这样做,您还可以保留索引对齐以处理响应。

async function getUsdWealthAsync(addresses) {
    let totalWealth = 0;
    let amountPromises = [];

    // For each of the currencies...
    for (var j = 0; j < currencies.length; j++) {
        // Create a set that will hold balance promises for this currency.
        const balancePromisesForCurrency = [];
        for (var i = 0; i < addresses.length; i++) {
            // Create those promises and add them to the set.
            balancePromisesForCurrency.push(
                currencies[j].contract.methods.balanceOf(addresses[i]).call()
            );
        }
        // Create a new promise that resolves to the list of balance results, ​
        // index-aligned to the addresses, for this currency. Add that Promise
        // to the set of per-currency Promises, index-aligned to the currencies
        // array.
        amountPromises.push(Promise.all(balancePromisesForCurrency));
    }

    // Create a new cumulative promise from the `amountPromises` array.
    await Promise.all(amountPromises).then(function (amountsForCurrency) {
        // For each of the balance lists received...
        amountsForCurrency.forEach((amounts, amountsIndex) => {
            // Get the corresponding currency.
            const currency = currencies[amountIndex];

            // Total up the balances scaled by the currency's USD rate.
            amounts.forEach((amount, idx) => {
                totalWealth += (+amount / 100) * currency.usdrate;
            });
        });
    })

    return totalWealth;
}```
于 2022-01-24T19:40:32.423 回答
0

你还有其他很好的答案。

另一种方式可能是,您可以将美元汇率与balanceOf承诺本身的结果一起附加,然后在解决承诺时,您可以直接访问美元汇率。

也许是这样的:

async function getUsdWealthAsync(addresses) {
  var totalWealth = 0;
  var amountPromises = [];
  for (var j = 0; j < currencies.length; j++) {
    for (var i = 0; i < addresses.length; i++) {
      const { usdrate, contract } = currencies[j];
      amountPromises.push(
        contract.methods.balanceOf(addresses[i]).call()
          .then((amount) => ({ amount, usdrate }))
      );
    }
  }

  const amounts = await Promise.all(amountPromises);

  for (var i = 0; i < amounts.length; i++) {
    const { amount, usdrate } = amounts[i];
    amount = Number.parseInt(amount);
    totalWealth += (amount / 100) * usdrate;
  }

  return totalWealth;
}
于 2022-01-24T19:41:59.067 回答