如何在映射中执行所有等待后才增加变量值,以便我可以执行承诺?



嘿,这是一个非常基本的问题,但我遇到了问题。我有以下代码:

var nonce = await web3.eth.getTransactionCount(fromAccount);
hashes.map(async hash => {
console.log(nonce)
const account = await web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY_1)
const transaction = await contract.methods.submitHash(hash);
const options  = {
nonce: web3.utils.toHex(nonce),
to      : transaction._parent._address,
data    : transaction.encodeABI(),
gas     : await transaction.estimateGas({from: account.address}),
gasPrice: web3.utils.toHex(web3.utils.toWei('20', 'gwei')),
};
const signed  = await web3.eth.accounts.signTransaction(options, account.privateKey);
const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
console.log(receipt)
nonce ++}

我只想在每次执行所有等待后增加随机数,即我想获得 1,2,3,4.. 作为随机数值。但问题是由于异步性质随机数在每个循环中获得相同的值,即 1,1,1,1。如何在每次循环执行中将其增加一?

问题是你在想要for循环的地方使用map。这有两个问题:

  1. 当你不使用它返回的数组时,使用map是没有意义的(有人在某个地方教授这种反模式并对他们的学生造成伤害(;

  2. map不会对
  3. async函数返回的承诺执行任何操作,因此所有async函数都并行运行

使用for循环,您就不会遇到这些问题:

let nonce = await web3.eth.getTransactionCount(fromAccount);
for (const hash of hashes) {
console.log(nonce);
const account = await web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY_1);
const transaction = await contract.methods.submitHash(hash);
const options = {
nonce   : web3.utils.toHex(nonce),
to      : transaction._parent._address,
data    : transaction.encodeABI(),
gas     : await transaction.estimateGas({from: account.address}),
gasPrice: web3.utils.toHex(web3.utils.toWei('20', 'gwei')),
};
const signed  = await web3.eth.accounts.signTransaction(options, account.privateKey);
const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
console.log(receipt);
++nonce;
}

由于您的for位于await工作的上下文中(async函数或很快成为模块的顶层(,因此它会在继续其逻辑之前等待await表达式。


如果工作可以并行完成,那么您可以在它返回的数组上使用mapawait Promise.all。在map回调中,使用nonce + index而不是递增,因为第一个哈希index0,下一个哈希1,依此类推:

// In parallel
let nonce = await web3.eth.getTransactionCount(fromAccount);
const results = await Promise.all(hashes.map(async (hash, index) => {
const thisNonce = nonce + index;
console.log(thisNonce);
const account = await web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY_1);
const transaction = await contract.methods.submitHash(hash);
const options = {
nonce   : web3.utils.toHex(thisNonce),
to      : transaction._parent._address,
data    : transaction.encodeABI(),
gas     : await transaction.estimateGas({from: account.address}),
gasPrice: web3.utils.toHex(web3.utils.toWei('20', 'gwei')),
};
const signed  = await web3.eth.accounts.signTransaction(options, account.privateKey);
const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
console.log(receipt);
}));
// If you're going to keep using `nonce`, do `nonce += results.length` here.

最新更新