重新思考 JavaScript 中的 async 循环
Using await in loops seems intuitive until your code silently stalls or runs slower than expected. If you’ve ever wondered why your API calls run one-by-one instead of all at once, or why map() and await don’t mix the way you’d expect, grab a chair. Let’s chat.
在循环里用 await 看似直观,直到代码悄悄卡住或运行得比预期慢。如果你曾疑惑为什么 API 调用是一个接一个地跑,而不是同时发起,或者为什么 map() 和 await 并不像你想象的那样配合,那就搬把椅子,咱们聊聊。
The problem: awaiting in a for loop
问题:在 for 循环中使用 await
Suppose you’re fetching a list of users one-by-one:
假设你正在逐个获取用户列表:
const users = [1, 2, 3]; for (const id of users) { const user = await fetchUser(id); console.log(user);
}
This works, but it runs sequentially: fetchUser(2) doesn’t start until fetchUser(1) finishes. That’s fine if order matters, but it’s inefficient for independent network calls.
这样写没问题,但它是顺序执行:fetchUser(2) 要等到 fetchUser(1) 完成后才会开始。如果顺序很重要,这没问题;但对独立的网络请求来说,效率很低。
A common point of confusion is using await inside map() without handling the resulting promises:
一个常见误区是在 map() 内部使用 await 却不处理返回的 promise:
const users = [1, 2, 3]; const results = users.map(async id => { const user = await fetchUser(id); return user;
}); console.log(results);
This works in terms of syntax and behavior (it returns an array of promises), but not in the way many expect. It doesn’t wait for the promises to resolve.
这在语法和行为上是有效的(它返回一个 promise 数组),但不符合许多人的预期。它不会等待 promise 完成。
To run the calls in parallel and get the final results:
要并行执行调用并获取最终结果:
const results = await Promise.all(users.map(id => fetchUser(id)));
Now all the requests run in parallel, and results contains the actual fetched users.
现在所有请求并行运行,results 包含实际获取到的用户。
Promise.all() fails fast, even if just one call breaks
Promise.all() 只要有一个调用失败就会立即失败
When using Promise.all(), a single rejection causes the entire operation to fail:
使用 Promise.all() 时,一次拒绝就会导致整个操作失败:
const results = await Promise.all( users.map(id => fetchUser(id)) );
If fetchUser(2) throws an error (e.g., 404 or network error), the entire Promise.all call will reject, and none of the results will be returned (including successful o...