TypeScript中带并发控制的批量Promise执行及类型优化问题
给mapConcurrent添加TypeScript强类型支持
你遇到的问题是原函数用了any类型导致类型信息丢失,我们可以通过TypeScript泛型让这个函数具备完整的类型推导能力,完美适配你需要的Promise返回类型。
类型化改造后的完整代码
function mapConcurrent<T, U>( items: Array<T>, maxConcurrent: number, fn: (item: T, index: number) => Promise<U> ): Promise<Array<U>> { let index = 0; let inFlightCntr = 0; let doneCntr = 0; const results = new Array<U>(items.length); let stop = false; return new Promise((resolve, reject) => { const runNext = () => { const i = index; inFlightCntr++; fn(items[index], index++) .then((val: U) => { doneCntr++; inFlightCntr--; results[i] = val; run(); }) .catch((err) => { stop = true; reject(err); }); }; const run = () => { while (!stop && inFlightCntr < maxConcurrent && index < items.length) { runNext(); } if (doneCntr === items.length) { resolve(results); } }; run(); }); }
关键类型说明
- 泛型
T:代表输入数组items中每个元素的类型 - 泛型
U:代表异步处理函数fn返回的Promise的结果类型 - 函数返回值
Promise<Array<U>>:自动推导为所有Promise结果组成的数组类型,完全和你的业务类型绑定
使用示例
比如你有一个返回Promise<{id: string}>的处理函数,用改造后的mapConcurrent会自动推断结果数组类型为Array<{id: string}>:
// 示例异步函数:返回包含id的对象 const fetchItem = (id: number): Promise<{id: string}> => { return Promise.resolve({ id: id.toString() }); }; // 输入数组 const itemIds = [1, 2, 3, 4, 5]; // 并发数设为3执行 mapConcurrent(itemIds, 3, fetchItem) .then(results => { // results的类型自动推断为 Array<{id: string}> console.log(results); // [{id: "1"}, {id: "2"}, ...] }) .catch(err => { console.error(err); });
额外说明
- 不需要手动指定泛型参数,TypeScript会根据你传入的
items和fn自动推导出T和U的类型 - 原有的并发控制逻辑完全保留,错误处理(只要有一个Promise reject就立即终止并reject)也和之前一致
- 如果后续想尝试第三方库,
p-limit是个不错的选择,它对TypeScript支持非常友好,用法也很简洁:import pLimit from 'p-limit'; const limit = pLimit(3); const promises = itemIds.map(id => limit(() => fetchItem(id))); Promise.all(promises).then(results => { /* ... */ });
内容的提问来源于stack exchange,提问作者Benjamin Bohec
相关产品推荐
相关产品推荐

