I have this function where I disabled eslint warning but I would like to improve the code. I understand that I should use promise.All(), but I am unsure how to proceed since I have two await in the for loop.
const getBatchLogsByHash = async (
chainId: number,
rpc: string,
batch: BlockRange,
) => {
const firstBlock = batch.startBlock;
const lastBlock = batch.endBlock;
const logs: Array<Log> = [];
/* eslint-disable no-await-in-loop */
for (let i = firstBlock; i <= lastBlock; i = 1) {
const block = await ethers.fetchBlock(chainId, rpc, i);
const blockLogs = await ethers.fetchLogsByBlockHash(
chainId,
rpc,
block.hash,
);
logs.push(...blockLogs);
}
return logs;
};
Thanks for the help
CodePudding user response:
You can use await
inside the promise executor in order to wait before you resolve the promise. Promise.all
then allows you to execute the lastBlock - firstBlock 1
ethers
operations in parallel. Since the order in which they finish cannot be predicted, you cannot use logs.push(...blockLogs)
. Use concat
instead to concatenate the blockLogs
to which the individual promises resolve in the order in which you started these promises.
var promises = [];
for (let i = firstBlock; i <= lastBlock; i = 1)
promises.push(new Promise(async function(resolve, reject) {
const block = await ethers.fetchBlock(chainId, rpc, i);
const blockLogs = await ethers.fetchLogsByBlockHash(
chainId,
rpc,
block.hash,
);
resolve(blockLogs);
}));
var logs = Array.prototype.concat.call(...await Promise.all(promises));
return logs;
But the following simpler code using .then
would be equivalent:
var promises = [];
for (let i = firstBlock; i <= lastBlock; i = 1)
promises.push(ethers.fetchBlock(chainId, rpc, i).then(
block => ethers.fetchLogsByBlockHash(
chainId,
rpc,
block.hash,
)
));
var logs = Array.prototype.concat.call(...await Promise.all(promises));
return logs;