mirror of
https://github.com/wyb10a10/cocos_creator_framework.git
synced 2026-05-11 16:22:41 +08:00
166 lines
5.4 KiB
TypeScript
166 lines
5.4 KiB
TypeScript
/*
|
||
* 任务队列管理器
|
||
* 1. 传入任务,进入队列顺序执行
|
||
* 2. 支持优先级(从小到大排序,priority越小优先级越高)
|
||
* 3. 支持队列Tag,允许多个互不影响的队列执行
|
||
* 4. 支持清理任务队列
|
||
* 5. 一个任务只能完成一次,避免代码的原因多次调用完成,导致后续任务提前执行
|
||
*
|
||
* 6. 调试模式下记录了每个Task添加时的堆栈,方便调试(可以快速查看哪个任务没有结束)
|
||
*
|
||
* 2018-5-7 by 宝爷
|
||
*/
|
||
|
||
// 任务结束回调
|
||
export type TaskFinishCallback = () => void;
|
||
// 任务执行回调
|
||
export type TaskCallback = (TaskFinishCallback : TaskFinishCallback) => void;
|
||
|
||
class TaskInfo {
|
||
public task: TaskCallback;
|
||
public priority: number;
|
||
public constructor(task: TaskCallback, priority: number) {
|
||
this.task = task;
|
||
this.priority = priority;
|
||
}
|
||
}
|
||
|
||
export class TaskQueue {
|
||
private _curTask: TaskInfo | null = null;
|
||
private _taskQueue: TaskInfo[] = Array<TaskInfo>();
|
||
|
||
// 添加一个任务,如果当前没有任务在执行,该任务会立即执行,否则进入队列等待
|
||
public pushTask(task: TaskCallback, priority: number = 0): void {
|
||
let taskInfo = new TaskInfo(task, priority);
|
||
if (this._taskQueue.length > 0) {
|
||
for (var i: number = this._taskQueue.length - 1; i >= 0; --i) {
|
||
if (this._taskQueue[i].priority <= priority) {
|
||
this._taskQueue.splice(i + 1, 0, taskInfo);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// 插到头部
|
||
this._taskQueue.splice(0, 0, taskInfo);
|
||
if (this._curTask == null) {
|
||
this.executeNextTask();
|
||
}
|
||
}
|
||
|
||
public clearTask(): void {
|
||
this._curTask = null;
|
||
this._taskQueue.length = 0;
|
||
}
|
||
|
||
private executeNextTask(): void {
|
||
let taskInfo = this._taskQueue.shift() || null;
|
||
this._curTask = taskInfo;
|
||
if (taskInfo) {
|
||
taskInfo.task(() => {
|
||
if (taskInfo === this._curTask) {
|
||
this.executeNextTask();
|
||
} else {
|
||
console.warn("your task finish twice!");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
export class TaskManager {
|
||
private static _instance: TaskManager | null= null;
|
||
private _taskQueues: { [key: number]: TaskQueue } = {}
|
||
|
||
public static getInstance(): TaskManager {
|
||
if (!this._instance) {
|
||
this._instance = new TaskManager();
|
||
}
|
||
return this._instance;
|
||
}
|
||
|
||
public static destory(): void {
|
||
this._instance = null;
|
||
}
|
||
|
||
private constructor() {
|
||
|
||
}
|
||
|
||
public pushTask(task: TaskCallback, priority: number = 0): void {
|
||
return this.getTaskQueue().pushTask(task, priority);
|
||
}
|
||
|
||
public pushTaskByTag(task: TaskCallback, tag: number, priority: number = 0): void {
|
||
return this.getTaskQueue(tag).pushTask(task, priority);
|
||
}
|
||
|
||
public clearTaskQueue(tag: number = 0): void {
|
||
let taskQueue = this._taskQueues[tag];
|
||
if (taskQueue) {
|
||
taskQueue.clearTask();
|
||
}
|
||
}
|
||
|
||
public clearAllTaskQueue(): void {
|
||
for (let queue in this._taskQueues) {
|
||
this._taskQueues[queue].clearTask();
|
||
}
|
||
this._taskQueues = {}
|
||
}
|
||
|
||
private getTaskQueue(tag: number = 0): TaskQueue {
|
||
let taskQueue = this._taskQueues[tag];
|
||
if (taskQueue == null) {
|
||
taskQueue = new TaskQueue();
|
||
this._taskQueues[tag] = taskQueue;
|
||
}
|
||
return taskQueue;
|
||
}
|
||
}
|
||
|
||
/* 测试用例:
|
||
* 1. 测试多个任务的执行顺序 + 优先级
|
||
* 2. 测试在执行任务的过程中动态添加新任务
|
||
|
||
export function testQueue() {
|
||
let creatTask = (idx, pri): TaskCallback => {
|
||
return (finish) => {
|
||
console.log(`execute task ${idx} priority ${pri}`);
|
||
finish();
|
||
};
|
||
};
|
||
let tag = 0;
|
||
let begin = (finish) => {
|
||
for (var i = 0; i < 100; ++i) {
|
||
let priority = 0;
|
||
if (i % 10 == 0) {
|
||
priority = -1;
|
||
} else if (i == 88) {
|
||
priority = 1;
|
||
} else if (i == 22) {
|
||
let task = creatTask(1.1, priority);
|
||
TaskManager.getInstance().pushTaskByTag(task, tag, priority);
|
||
task = creatTask(1.2, priority);
|
||
TaskManager.getInstance().pushTaskByTag(task, tag, priority);
|
||
task = creatTask(1.3, priority);
|
||
TaskManager.getInstance().pushTaskByTag(task, tag, priority);
|
||
} else if (i == 51 && tag == 2) {
|
||
// 清理之后,添加的任务会立即执行...
|
||
TaskManager.getInstance().clearTaskQueue(tag);
|
||
}
|
||
let task = creatTask(i, priority);
|
||
Object.defineProperty(task, "idx", { value: i });
|
||
TaskManager.getInstance().pushTaskByTag(task, tag, priority);
|
||
}
|
||
console.log("add task finish, start test");
|
||
finish();
|
||
// 测试重复调用结束
|
||
finish();
|
||
// tag为2时的finish两次都会报警告,因为begin已经被清理了
|
||
}
|
||
TaskManager.getInstance().pushTaskByTag(begin, tag);
|
||
tag = 2;
|
||
TaskManager.getInstance().pushTaskByTag(begin, tag);
|
||
|
||
}*/
|