import { Framework } from "../Framework"; export type NextFunction = (nextArgs?: any) => void; export type AsyncCallback = (next: NextFunction, params: any, args: any) => void; interface AsyncTask { /** * 任务uuid */ uuid: number; /** * 任务开始执行的回调 * params: push时传入的参数 * args: 上个任务传来的参数 */ callbacks: Array; /** * 任务参数 */ params: any } export class AsyncQueue { private _runningAsyncTask: AsyncTask = null; //正在运行的任务 private static _$uuid_count: number = 1; //任务task的唯一标识 private _queues: Array = []; //任务队列 complete: Function | null = null; //任务队列完成回调 get queues(): Array { return this._queues; } private _isProcessingTaskUUID: number = 0; //正在执行的异步任务标识 private _enable: boolean = true; //是否启动 /** * 是否开启可用 */ get enable() { return this._enable; } /** * 是否开启可用 */ set enable(val: boolean) { if (this._enable !== val) { this._enable = val; if (val && this.size > 0) { this.play(); } } } /** * push一个异步任务到队列中 * 返回任务uuid */ push(callback: AsyncCallback, params: any = null) { let uuid = ++AsyncQueue._$uuid_count; this._queues.push({ uuid: uuid, callbacks: [callback], params: params }) return uuid; } /** * push多个任务,多个任务函数会同时执行, * 返回任务uuid */ pushMulti(params: any, ...callbacks: AsyncCallback[]) { let uuid = ++AsyncQueue._$uuid_count; this._queues.push({ uuid: uuid, callbacks: callbacks, params: params }) return uuid; } /** 移除一个还未执行的异步任务 */ remove(uuid: number) { if (this._runningAsyncTask?.uuid === uuid) { console.error("正在执行的任务不可以移除"); return; } for (let i = 0; i < this._queues.length; ++i) { if (this._queues[i].uuid === uuid) { this._queues.splice(i, 1); break; } } } /** * 队列长度 */ get size(): number { return this._queues.length; } /** * 是否有正在处理的任务 */ get isProcessing(): boolean { return this._isProcessingTaskUUID > 0; } /** * 队列是否已停止 */ get isStop(): boolean { return (this._queues.length > 0 || this.isProcessing) ? false : true; } /** 正在执行的任务参数 */ get runningParams() { return this._runningAsyncTask ? this._runningAsyncTask.params : null; } /** * 清空队列 */ clear() { this._queues = []; this._isProcessingTaskUUID = 0; this._runningAsyncTask = null; } protected _next_task(taskUUID: number, args: any = null) { if (this._isProcessingTaskUUID === taskUUID) { this._isProcessingTaskUUID = 0; this._runningAsyncTask = null; this.play(args); } else { if (this._runningAsyncTask) { console.log(this._runningAsyncTask); } } } /** * 跳过当前正在执行的任务 */ step() { (this.isProcessing) && this._next_task(this._isProcessingTaskUUID); } /** * 开始运行队列 */ play(args: any = null) { if (this.isProcessing || !this._enable) { return; } let actionData: AsyncTask = this._queues.shift()!; if (actionData) { this._runningAsyncTask = actionData; let taskUUID: number = actionData.uuid; this._isProcessingTaskUUID = taskUUID; let callbacks: Array = actionData.callbacks; if (callbacks.length == 1) { let nextFunc: NextFunction = (nextArgs: any = null) => { this._next_task(taskUUID, nextArgs); } callbacks[0](nextFunc, actionData.params, args); } else { // 多个任务函数同时执行 let fnum: number = callbacks.length; let nextArgsArr: any[] = []; let nextFunc: NextFunction = (nextArgs: any = null) => { --fnum; nextArgsArr.push(nextArgs || null); if (fnum === 0) { this._next_task(taskUUID, nextArgsArr); } } let knum = fnum; for (let i = 0; i < knum; ++i) { callbacks[i](nextFunc, actionData.params, args); } } } else { this._isProcessingTaskUUID = 0; this._runningAsyncTask = null; (this.complete) && this.complete(args); } } /** * 往队列中push一个延时任务 * @param time 时间(秒) * @param callback 时间到了之后回调 */ yieldTime(time: number, callback: Function = null) { let task = function (next: Function, params: any, args: any) { Framework.time.scheduleOnce(() => { callback && callback(); next(args); }, time); } this.push(task, { des: "AsyncQueue.yieldTime" }); } /** * 返回一个执行函数,执行函数调用count次后,next将触发 * @param count * @param next * @return 返回一个匿名函数 */ static excuteTimes(count: number, next: Function = null) { let fnum: number = count; let tempCall = () => { --fnum; if (fnum === 0) { next && next(); } } return tempCall; } } /** * let queue: AsyncQueue = new AsyncQueue(); * //添加一个异步任务 * queue.push(async (next: NextFunction, params: any, args: any) => { * load("",type,(error,res)=>{ * next && next(); * }); * }); * * //任务完成后的回调函数 * queue.complete = () => { * * } * * //执行异步任务 * queue.play(); */