Add new code smell for await inside loop

  • Description
    Disallow await inside of loops. Performing an operation on each element of an iterable is a common task. However, performing an await as part of each operation is an indication that the program is not taking full advantage of the parallelization benefits of async/await. Usually, the code should be refactored to create all the promises at once, then get access to the results using Promise.all(). Otherwise, each successive operation will not start until the previous one has completed.
  • snippet of Noncompliant Code
async function foo(things) {
  const results = [];
  for (const thing of things) {
    // Bad: each loop iteration is delayed until the entire asynchronous operation completes
    results.push(await bar(thing));
  }
  return baz(results);
}
  • snippet of Compilant Code
async function foo(things) {
  const results = [];
  for (const thing of things) {
    // Good: all asynchronous operations are immediately started.
    results.push(bar(thing));
  }
  // Now that all the asynchronous operations are running, here we wait until they all complete.
  return baz(await Promise.all(results));
}
  • exceptions to the Noncompliant Code, i.e. conditions in which the noncompliant code should not raise an issue so that we reduce the number of False Positives.
    In many cases the iterations of a loop are not actually independent of each-other. For example, the output of one iteration might be used as the input to another. Or, loops may be used to retry asynchronous operations that were unsuccessful. Or, loops may be used to prevent your code from sending an excessive amount of requests in parallel. In such cases it makes sense to use await within a loop.
  • external references and/or language specifications
    no-await-in-loop - ESLint - Pluggable JavaScript Linter
  • type : Code Smell
  • Tags : Javascript, Typescript
13 Likes

Hi Samarpan,

Thanks for raising this, sorry for the long time to respond!

Indeed this is a nice rule and we’ll look into it, here’s the ticket:
https://sonarsource.atlassian.net/browse/JS-319

2 Likes