追記:【注意】本記事の実装にはいくつかの改善点があります。内容と改善されている別実装はコメントを参照のこと。
やりたいこと
ただの並列処理ではなく、多重度に制限を付けられる並列処理。
例えば、100件の処理があったとき10を指定すると最大並列10で並列処理をして実施する
ユースケース
APIをたくさん叩くときに多重度の制限やレートリミットがある場合など。
実装
const limitedParallel = async <P, R>(
limit: number,
params: P[],
process: (param: P) => Promise<R>,
): Promise<R[]> => {
if (limit <= 0) return []
const reqGroups: Promise<R[]>[] = []
for (let i = 0; i < limit; i++) {
reqGroups.push(
new Promise<R[]>(async (resolve) => {
const ret: R[] = []
for (let j = i; j < params.length; j += limit) {
const r = await process(params[j])
ret.push(r)
}
resolve(ret)
}),
)
}
return Promise.all(reqGroups).then((ret) => {
return Array.prototype.concat.apply([], ret)
})
}
メモ、備考
- limit === 0 のときはアサーションや例外でも良いかもしれない
- Array.prototype.concat.apply([], ret)はそのうちret.flat()に置き換える
- 他に良さそうな実装があったら教えてください