在项目中我发现有的同学进度加载比较混乱,想到什么就加什么,后期进度显示要么停住,要么乱了。因此今天随手写了个进度管理器分享给大家(Github):
任务管理器:
export type Progressor = (p: number) => void;
export type Runner = (task: Task, progress: Progressor) => Promise<boolean>;
export class Task {
name: string;
weight: number;
runner: Runner;
constructor(name: string, weight: number, runner: Runner) {
this.name = name;
this.weight = weight;
this.runner = runner;
}
}
export class TaskManager {
private _tasks: Task[] = [];
private _totalWeight: number = 0;
add(name: string, weight: number, runnder: Runner) {
this._tasks.push(new Task(name, weight, runnder));
this._totalWeight += weight;
}
async runSerial(progress: Progressor, thisObj: any) {
var weight = 0;
let totalTime = Date.now();
progress?.call(thisObj, 0);
for (let task of this._tasks) {
console.log(`begin task ${task.name}`);
let dt = Date.now();
let ret = await task.runner(task, (p) => {
let w = weight + task.weight * p;
let pp = w / this._totalWeight;
progress?.call(thisObj, pp);
// console.log(`task ${task.name} progress ${pp}`);
});
if (!ret) {
return false;
}
weight += task.weight;
let pp = weight / this._totalWeight;
progress?.call(thisObj, pp);
console.log(`task ${task.name} done, cost ${Date.now() - dt}ms`);
}
console.log(`total cost ${Date.now() - totalTime}ms`);
return true;
}
async runParallel(progress: Progressor, thisObj: any) {
var weight = 0;
let tasks = this._tasks.map(task => {
return new Promise(async (resolve, reject) => {
console.log(`begin task ${task.name}`);
let dt = Date.now();
let ret = await task.runner(task, (p) => {
let w = weight + task.weight * p;
let pp = w / this._totalWeight;
progress?.call(thisObj, pp);
// console.log(`task ${task.name} progress ${pp}`);
});
weight += task.weight;
console.log(`task ${task.name} done, cost ${Date.now() - dt}ms`);
let pp = weight / this._totalWeight;
progress?.call(thisObj, pp);
resolve(ret);
});
});
let totalTime = Date.now();
let ret = await Promise.all(tasks);
console.log(`total cost ${Date.now() - totalTime}ms`);
if (ret.indexOf(false) >= 0) {
return false;
}
return true;
}
}
使用方式:
async loading() {
let loadMgr = new TaskManager();
loadMgr.add("加载资源包", 1, async (t, p) => {
await ResManager.loadResBundle();
return true;
});
loadMgr.add("加载配置表", 3, async (t, p) => {
await ResManager.loadDirRes("data", (p0) => {
p(p0 * 0.008);
});
await ConfigManager.I.loadConfig();
return true;
});
loadMgr.add("登录", 1, async (t, p) => {
await this.login();
return true;
});
loadMgr.add("UI预加载", 3, async (t, p) => {
await ResManager.loadABDirRes("ui", (p0) => {
p(p0 * 0.007);
});
return true;
});
loadMgr.add("加载特效", 1, async (t, p) => {
await ResManager.loadDirRes("anim-effects", (p0) => {
p(p0 * 0.001);
});
return true;
});
loadMgr.add("加载音效", 1, async (t, p) => {
await ResManager.loadDirRes("audio", (p0) => {
p(p0 * 0.001);
});
return true;
});
loadMgr.add("基础设置", 1, async (t, p) => {
return true;
});
loadMgr.add("加载场景", 10, async (t, p) => {
let ab = ResManager.getResBundle();
let sceneName = "game";
return await new Promise(resolve => {
ab.preloadScene(sceneName, null,
(finish, total, item) => {
if(total < 10) {
p(0);
}else{
let cur = finish / total;
p(cur);
}
}, () => {
director.loadScene(sceneName);
resolve(true);
});
});
});
loadMgr.runSerial((p) => {
this.progress = p;
}, this);
}
可以看到,每个进度只需要关心当前任务在整个任务中所占的权重以及,当前任务自身的进度就行了。
