Why forEach Is Losing Favor: Switch to for...of for Async JavaScript Loops

The article explains why Array.prototype.forEach is increasingly discouraged in modern JavaScript, especially with async/await, and demonstrates how replacing it with a for...of loop resolves async handling, break/continue control, and improves code clarity.

JavaScript
JavaScript
JavaScript
Why forEach Is Losing Favor: Switch to for...of for Async JavaScript Loops

If you follow popular open‑source projects, you’ll notice a trend: using Array.prototype.forEach is increasingly discouraged in code reviews, with a recommendation to replace it with a for...of loop. forEach was once the elegant functional‑programming tool of the ES5 era; why has it fallen out of favor today?

1. Async code pitfalls

The most common reason to abandon forEach is that, now that async/await is the standard for asynchronous programming, forEach feels out of place.

Problem: forEach cannot correctly handle await.

The callback of forEach runs in its own function scope and does not wait for any asynchronous operation. It executes all iterations synchronously without pausing for a Promise.

Typical erroneous example:

const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const ids = [1, 2, 3];

async function processUsers(ids) {
  console.log('开始处理...');
  ids.forEach(async (id) => {
    await sleep(1000); // expect 1‑second wait per iteration
    console.log(`处理完用户 ${id}`);
  });
  console.log('...全部处理完毕');
}

processUsers(ids);
// Actual output (approx. 1 s later, almost simultaneous):
// 开始处理...
// ...全部处理完毕
// 处理完用户 1
// 处理完用户 2
// 处理完用户 3

From the result you can see that the "...全部处理完毕" log is printed immediately; forEach never waited for the internal await. It merely triggered three parallel sleep operations, which defeats the intention of sequential processing.

Solution: Use for...of.

The for...of loop is the perfect partner for await. It is a true loop construct, not a function call, so await can pause the entire loop until the Promise resolves.

For scenarios that require serial execution of asynchronous tasks, for...of is indispensable.

2. Cannot break or skip the loop

Another native limitation of forEach is the inability to use break or continue as you can with a traditional for loop.

Using return inside a forEach callback only exits that callback, behaving like continue, but it does not terminate the whole loop.

const numbers = [1, 2, 3, 4, 5];

numbers.forEach(num => {
  if (num === 3) {
    // Want to stop the loop here, but cannot! return only skips this iteration
    return;
  }
  console.log(num);
});
// Output: 1, 2, 4, 5

To forcefully break, you would have to throw an exception, which is considered non‑elegant and is discouraged by most coding standards.

In contrast, for...of fully supports break, continue, and other flow‑control keywords, making the code logic clearer and more intuitive.

Of course, this does not mean forEach should be completely abandoned. In certain specific scenarios it still has its place:

When the operation is entirely synchronous and you do not need to break or skip, the chainable syntax of forEach remains elegant.

When combined with other array methods (e.g., filter, map), forEach can serve as a clean terminal step, preserving a consistent coding style.

Example of a synchronous use case:

['error', 'warning', 'info'].forEach(level => console.log(level));
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptasync/awaitforeachfor...ofloop control
JavaScript
Written by

JavaScript

Provides JavaScript enthusiasts with tutorials and experience sharing on web front‑end technologies, including JavaScript, Node.js, Deno, Vue.js, React, Angular, HTML5, CSS3, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.