UNPKG

luxi-record-utils

Version:
110 lines (109 loc) 4.19 kB
/* ** 并发控制类 ** @params taskQueue任务队列,每个任务返回promise ** @params maxTaskRunner 为最大并发数量 */ export interface PromiseTask { (): Promise<any> } export class ConcurrencyControl { private taskQueue: PromiseTask[] = [] private isStoped: boolean = true private maxTaskRunner: number = 0 private tasksResult: any[] = [] private taskRunning: number = 0 private taskRunningIndex: number = 0 constructor(taskQueue: PromiseTask[], maxTaskRunner: number) { let runner: number = maxTaskRunner if (!taskQueue || !Array.isArray(taskQueue)) { throw new Error('The concurrency control constructor must pass in the concurrency queue parameter') } if (!maxTaskRunner || !(typeof (maxTaskRunner) === 'number') || maxTaskRunner !== maxTaskRunner || maxTaskRunner === Infinity) { console.warn('The concurrency control number is invalid, The default is one') runner = 1 } this.taskQueue = taskQueue this.maxTaskRunner = runner } public run(): Promise<any[]> { this.isStoped = false return new Promise((resolve, reject) => { const runTask = () => { while (this.taskRunning < this.maxTaskRunner && this.taskQueue.length && !this.isStoped) { const task = this.taskQueue.shift() this.taskRunning++ this.taskRunningIndex++ const resultIndex = this.taskRunningIndex - 1 if (task) { const taskResult = task() if (taskResult instanceof Promise) { taskResult.then((res: any) => { this.tasksResult[resultIndex] = res this.taskRunning-- if (!this.isStoped) { runTask() } }).catch((err: any) => { this.isStoped = true reject(err) }) } else { this.tasksResult[resultIndex] = taskResult this.taskRunning-- runTask() } } } if (this.taskRunning === 0 && this.taskQueue.length === 0) { resolve(this.tasksResult) } } runTask() }) } public stop(): void { this.isStoped = true } public get result() { return this.tasksResult } } /* ** 简易版并发控制类 ** @params task任务队列,每个任务返回promise ** @params limit为最大并发数量 */ export function asyncTasks(task: PromiseTask[], limit: number = 1): Promise<any> { if (!task || !Array.isArray(task)) { throw new Error('Requires asynchronous queues') } let index = 0, resulet: any[] = [] let queue = Array(limit).fill(null) queue = queue.map(() => { return new Promise((resolve, reject) => { const runTask = () => { if (index >= task.length) { resolve('') return } const taskItem = task[index] const resuletIdnex = index index++ const promise = taskItem() if (promise instanceof Promise) { promise.then((res) => { resulet[resuletIdnex] = res runTask() }).catch((err) => { reject(err) }) } else { resulet[resuletIdnex] = promise runTask() } } runTask() }) }) return Promise.all(queue).then(() => { return resulet }) }