直接用 array.map() 调用 async 函数会返回 pending promise 数组;需用 promise.all + map 实现并行映射,或 reduce 实现串行映射,并注意并发控制。

直接用 array.map() 调用 async 函数,会得到一堆 pending 的 Promise,不是你想要的数组结果。关键在于:map 本身是同步的,它不等异步操作完成就返回了;你需要让整个映射过程真正“等待”每个异步操作结束。
用 Promise.all + map 实现并行异步映射
这是最常用、最直观的方式。map 负责把每个元素转成一个 Promise,Promise.all 负责等待全部完成并收集结果。
- 所有异步操作同时发起,适合相互独立、无顺序依赖的场景(比如批量请求不同用户的资料)
- 只要有一个失败,
Promise.all就整体 reject,需配合 try/catch 或.catch()处理
示例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const res = await fetch(`/api/users/${id}`);
return res.json();
}
async function fetchAllUsers(ids) {
try {
const users = await Promise.all(ids.map(fetchUser));
return users;
} catch (err) {
console.error("获取用户失败", err);
throw err;
}
}
用 reduce 实现串行异步映射
如果后一个异步操作依赖前一个的结果(比如按顺序上传文件、链式调用 API),就不能并行,得一个接一个执行。
- 利用
reduce的累积特性,把上一步的 await 结果传给下一步 - 写法稍复杂,但逻辑清晰、错误可逐个捕获
示例:
async function sequentialMap(array, asyncFn) {return array.reduce(async (accPromise, item) => {
const acc = await accPromise;
const result = await asyncFn(item);
return [...acc, result];
}, Promise.resolve([]));
}
// 使用
sequentialMap([1, 2, 3], fetchUser).then(console.log);
封装 asyncFilter、asyncFind 等衍生高阶函数
map 不是唯一能异步化的高阶函数。filter、find、some 等同样可以改造,核心思路一致:先用 map + async 得到 Promise 数组,再用 Promise.all 等待,最后用原生方法处理布尔结果。
-
asyncFilter:先并行执行判断函数,拿到布尔值数组,再用原生 filter 筛选原数组 -
asyncFind:可配合for...of串行执行,找到第一个满足条件的就返回,避免全量请求
示例(asyncFilter):
async function asyncFilter(array, predicate) {const results = await Promise.all(array.map(predicate));
return array.filter((_, i) => results[i]);
}
async function isAvailable(id) {
const res = await fetch(`/api/check/${id}`);
return res.ok;
}
asyncFilter([101, 102, 103], isAvailable); // 返回可用 ID 数组
注意并发控制,避免压垮服务
上面的 Promise.all 方式在数组很大时,会瞬间发出大量请求,可能触发限流或超时。真实项目中常需限制并发数。
- 可用
p-limit这类轻量库,或手写“批处理 + 递归”逻辑 - 例如每次只并发 3 个请求,等其中任一完成,立即发起下一个,保持队列恒定
简单手写思路:
async function mapLimit(array, limit, asyncFn) {const results = [];
const executing = [];
for (const item of array) {
const p = Promise.resolve().then(() => asyncFn(item));
results.push(p);
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= limit) await Promise.race(executing);
}
return Promise.all(results);
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










