This rule raises an issue when a Promise is awaited inside a loop body, forcing each iteration’s asynchronous operation to complete
before the next one starts.
async/await lets asynchronous operations run concurrently: multiple promises can be created and left pending while other
work proceeds, then resolved together once they have all settled.
Awaiting a promise inside a loop breaks this benefit. Each iteration blocks until the previous await resolves, so independent
asynchronous operations that could run at the same time are instead executed strictly one after another. For n iterations that each take
roughly the same amount of time, this multiplies the total waiting time by n instead of running the operations concurrently.
This pattern also compounds the impact of failures: if an early iteration’s operation fails, none of the later, independent operations even get started, even though they don’t depend on the failed one.
Instead of awaiting each operation before starting the next, start every asynchronous operation first and await them together, for example with
Promise.all(). This lets the independent operations run concurrently while still giving a single point to retrieve every result or handle
a failure.
async function fetchAll(urls) {
const responses = [];
for (const url of urls) {
const response = await fetch(url); // Noncompliant: each fetch waits for the previous one to finish
responses.push(response);
}
return responses;
}
async function fetchAll(urls) {
const responses = await Promise.all(urls.map(url => fetch(url)));
return responses;
}
This rule does not apply to for await…of loops, since consuming an asynchronous iterator one item at a time is the explicit purpose
of that construct.
Sequential awaiting is also the correct choice, and an issue raised by this rule can be safely dismissed, when the iterations are not actually independent, for example when: