Home > front end >  Multiple await in for loop (no-await-in-loop)
Multiple await in for loop (no-await-in-loop)

Time:01-21

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;
  • Related