嘿,这是一个非常基本的问题,但我遇到了问题。我有以下代码:
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
。这有两个问题:
-
当你不使用它返回的数组时,使用
map
是没有意义的(有人在某个地方教授这种反模式并对他们的学生造成伤害(; async
函数返回的承诺执行任何操作,因此所有async
函数都并行运行
map
不会对使用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
表达式。
如果工作可以并行完成,那么您可以在它返回的数组上使用map
和await Promise.all
。在map
回调中,使用nonce + index
而不是递增,因为第一个哈希index
0
,下一个哈希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.