JavaScript by Example

Loops

for, for-of, for-in, forEach - which to use and why forEach can't be awaited.

JavaScript offers several loop constructs. Picking the right one matters for correctness, readability, and async behavior.

A classic for loop gives full control over the index - useful when you need the position, not just the value.

const items = ["a", "b", "c"];
 
for (let i = 0; i < items.length; i++) {
  console.log(i, items[i]);
}
// 0 a
// 1 b
// 2 c

for-of iterates over the values of any iterable - arrays, strings, Sets, Maps, and generators. It's the modern default for sequential iteration.

const colors = ["red", "green", "blue"];
 
for (const color of colors) {
  console.log(color);
}
// red
// green
// blue

for-in iterates over the keys of an object - including enumerable inherited properties. Avoid it on arrays; it can surface unexpected prototype keys and the order is not guaranteed.

const user = { name: "Ana", role: "admin" };
 
for (const key in user) {
  console.log(key, user[key]);
}
// name Ana
// role admin

.forEach passes each value to a callback but cannot be break-ed out of and cannot be awaited. for-of is safer in both situations.

const ids = [1, 2, 3];
 
// WRONG - forEach does not await the async callback
ids.forEach(async (id) => {
  await saveToDb(id); // runs fire-and-forget
});
 
// CORRECT - sequential async iteration
for (const id of ids) {
  await saveToDb(id);
}
 
// CORRECT - parallel with bounded result collection
await Promise.all(ids.map((id) => saveToDb(id)));

In production

The forEach + async trap is one of the most common async bugs in Node.js codebases: the function returns immediately while the callbacks run in the background, so callers believe the work is done before it is. Use for-of with await for serial processing, or Promise.all with .map for parallel - and be explicit about which concurrency model you want. Unbounded Promise.all across 500 records can saturate a database connection pool just as effectively as a bug.

Enjoyed this? Get more essays on software craft delivered to your inbox.

Subscribe free