/** 按并发限制执行一个函数数组,同时只能运行限制数量的异步函数 * @example * ```ts * const funcs = list.map((item) => async () => {}) * runWithLimit(funcs, 3).then(() => { console.log("done") }) * ``` * @param funcs 要执行的函数数组,函数必须返回 Promise * @param limit 并发限制数量 * * */ export function runWithLimit(funcs: (() => Promise)[], limit: number) { return new Promise((resolve) => { let doneList: any[] = [] let runningList: any[] = [] let waitList: any[] = funcs.slice(0) tick() function tick() { let readyList: any[] = [] while (waitList.length > 0 && readyList.length + runningList.length < limit) { let func = waitList.shift() readyList.push(func) } // console.log("[runWithLimit] tick", { limit, readyListLength: readyList.length }) for (const func of readyList) { let promise: Promise = func() runningList.push(promise) promise.finally(() => { doneList.push(promise) runningList.splice(runningList.indexOf(promise), 1) tick() }) } if (runningList.length == 0 && waitList.length == 0) { // console.log("[runWithLimit] done", doneList) resolve(doneList) } } }) }