Promise.all 使用嵌套循环的参数转换结果
Promise.all convert result with parameter from nested loop
以下循环调用异步函数,这里是使用 web3 的智能合约交互。我想通过调用 balanceOf() 获得令牌数组的余额,然后使用附加的 usdrate 将其转换。对于并行处理,我使用 Promise.all。显然,下面的 Promise.all() 访问 [I % currency.length] 的函数不起作用,因为不能保证排序结果。
我的问题是,如何将金额乘以附加到代币的正确美元汇率并仍然使用 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;
}
async
函数总是 return a Promise
,您可以定义一个异步函数来接收地址和货币,并且 returns a Promise
计算已经完成,所以你没有索引问题。像
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
调用的最后一行应该是您拥有的所有金额的总和
为什么不使用嵌套 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;
}```
您还有其他很好的答案。
另一种方法是,您可以在承诺本身中附加美元汇率以及 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;
}
以下循环调用异步函数,这里是使用 web3 的智能合约交互。我想通过调用 balanceOf() 获得令牌数组的余额,然后使用附加的 usdrate 将其转换。对于并行处理,我使用 Promise.all。显然,下面的 Promise.all() 访问 [I % currency.length] 的函数不起作用,因为不能保证排序结果。
我的问题是,如何将金额乘以附加到代币的正确美元汇率并仍然使用 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;
}
async
函数总是 return a Promise
,您可以定义一个异步函数来接收地址和货币,并且 returns a Promise
计算已经完成,所以你没有索引问题。像
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
调用的最后一行应该是您拥有的所有金额的总和
为什么不使用嵌套 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;
}```
您还有其他很好的答案。
另一种方法是,您可以在承诺本身中附加美元汇率以及 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;
}