需求
设计一个方法,限制进入方法的异步函数数组的并发数。
分析
- 异步函数,使用返回Promise对象的函数实现;
- 调用数(limit)可配置;
- 可以通过Promise.race来实现有限并发和完成后更新并发列表的功能。
优化
- 使用Typescript实现,优化类型提示;
- 参照Promise.allSettled的Return风格,顺序返回异步函数结果集Promise对象;
实现
function promiseQueue<T extends readonly (() => Promise<any>)[] | []>(
promiseList: T,
limit = 5
): Promise<{
-readonly [P in keyof T]: T[P] extends () => infer K
? PromiseSettledResult<Awaited<K>>
: never;
}> {
limit = Math.min(promiseList.length, limit);
let pendingList: Promise<any>[] = [];
const result: PromiseSettledResult<any>[] = [];
// 装饰异步方法,实现待请求队列
const _promiseList = promiseList.map((promiseFn, idx) => () => {
const promise = promiseFn()
.then(value => {
result[idx] = {
status: 'fulfilled',
value
};
})
.catch(reason => {
result[idx] = {
status: 'rejected',
reason
};
})
.finally(() => {
pendingList = pendingList.filter(_promise => _promise !== promise);
});
return promise;
});
// 请求中队列
pendingList = Array.from({ length: limit }, () => 0).map(() =>
_promiseList.shift()!()
);
// 返回一个Promise
return new Promise<any>(resolve => {
// 递归
const racer = () => {
if (!_promiseList.length && !pendingList.length) {
// 当待请求队列&请求中队列为空时,返回结果
return resolve(result);
}
// 请求入列
if (_promiseList.length) pendingList.push(_promiseList.shift()!());
return Promise.race(pendingList).finally(() => {
racer();
});
};
racer();
});
复制代码