export type RunTask = (...args: T[]) => Promise export interface QueueContent { task: T resolve: () => void reject: (err?: any) => void } export class Pool { queue: Array> = [] processing: Array> = [] constructor(private runTask: RunTask, private limit: number) { } enqueue(task: T) { return new Promise((resolve, reject) => { this.queue.push({ task, resolve, reject }) this.check() }) } run(item: QueueContent) { this.queue = this.queue.filter(v => v !== item) this.processing.push(item) this.runTask(item.task).then( () => { this.processing = this.processing.filter(v => v !== item) item.resolve() this.check() }, err => item.reject(err) ) } check() { const processingNum = this.processing.length const availableNum = this.limit - processingNum this.queue.slice(0, availableNum).forEach(item => { this.run(item) }) } }