Array.prototype.map() 的异步陷阱:为什么 await 没生效?
map 里的异步函数,返回的是 Promise 数组,不是结果数组。忘了 Promise.all,代码直接跑飞。
事故现场
JavaScript
// 期望:依次获取 3 个用户详情
const userIds = [1, 2, 3];
const users = userIds.map(async id => {
return await fetchUser(id);
});
console.log(users); // [Promise, Promise, Promise] ❌ 不是用户数据!
后续操作直接报错:
JavaScript
users.forEach(u => console.log(u.name));
// undefined undefined undefined
原因:map 不会等待异步完成
JavaScript
// map 的回调返回什么,结果就是什么
[1, 2, 3].map(x => x * 2); // [2, 4, 6] ✅ 同步
[1, 2, 3].map(async x => x * 2); // [Promise, Promise, Promise] ⚠️ 异步
async 函数隐式返回 Promise,map 原封不动收集这些 Promise。
正确写法
方案 1:Promise.all 解包(推荐)
JavaScript
const userIds = [1, 2, 3];
const users = await Promise.all(
userIds.map(id => fetchUser(id))
);
console.log(users); // [{...}, {...}, {...}] ✅
方案 2:for...of 顺序执行(需要控制并发)
JavaScript
const users = [];
for (const id of userIds) {
const user = await fetchUser(id); // 依次执行,非并发
users.push(user);
}
方案 3:forEach 的坑(别用)
JavaScript
// ❌ 错误:forEach 不会等待异步完成
userIds.forEach(async id => {
const user = await fetchUser(id);
console.log(user); // 循环结束后才执行,顺序混乱
});
进阶:带错误处理的批量请求
JavaScript
const results = await Promise.allSettled(
userIds.map(id => fetchUser(id))
);
const users = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
一句话总结
map + async = Promise 数组,想拿结果包一层 Promise.all。异步循环用 for...of,别用 forEach。
异步是传染病,一个函数 async,调用链全得 await。
