first
This commit is contained in:
12
extensions/app/assets/lib/debug.meta
Normal file
12
extensions/app/assets/lib/debug.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "e939f63c-c853-403c-aed7-b8f0925106f0",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
40
extensions/app/assets/lib/debug/debug.ts
Normal file
40
extensions/app/assets/lib/debug/debug.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { DEBUG, DEV } from 'cc/env';
|
||||
|
||||
function jsGetSet(obj: unknown, prop: string, getter: Function, setter?: Function) {
|
||||
Object.defineProperty(obj, prop, {
|
||||
get: getter as any,
|
||||
set: setter as any,
|
||||
enumerable: false,
|
||||
configurable: false
|
||||
});
|
||||
}
|
||||
function clear(object: Record<string | number, any>) {
|
||||
if (!object) return;
|
||||
for (const key of Object.keys(object)) {
|
||||
delete object[key];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 将某个变量设置为不可观测(不可在浏览器中打印)
|
||||
* @param owner object | string | number | boolean | Array | Function | ...
|
||||
* @param callback 被观测时触发回调
|
||||
* @returns
|
||||
*/
|
||||
export function unobservable(owner: unknown, callback?: Function) {
|
||||
if (DEV || DEBUG) return;
|
||||
if (!owner) return;
|
||||
function define() {
|
||||
function accessor() {
|
||||
if (callback) {
|
||||
callback();
|
||||
} else {
|
||||
clear(owner);
|
||||
}
|
||||
}
|
||||
try {
|
||||
jsGetSet(owner, 'unobservable', accessor.bind(null, 'de' + 'bu' + 'gg' + 'er'));
|
||||
}
|
||||
catch (e) { !0; }
|
||||
}
|
||||
define();
|
||||
}
|
||||
9
extensions/app/assets/lib/debug/debug.ts.meta
Normal file
9
extensions/app/assets/lib/debug/debug.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "c0d5da3b-23f0-400e-85bb-6c754b9c08eb",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
extensions/app/assets/lib/logger.meta
Normal file
9
extensions/app/assets/lib/logger.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "140d98c1-6885-4e37-bf16-2ee67ffe087e",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
77
extensions/app/assets/lib/logger/logger.ts
Normal file
77
extensions/app/assets/lib/logger/logger.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { DEV } from 'cc/env';
|
||||
|
||||
interface ILog {
|
||||
(title: string, ...args: any[]): void
|
||||
}
|
||||
|
||||
function empty() { }
|
||||
|
||||
/**
|
||||
* 日志管理类,用于统一日志输出格式
|
||||
*/
|
||||
export class Logger {
|
||||
static setting: {
|
||||
filter: Array<'log' | 'warn' | 'error'>
|
||||
} = {
|
||||
filter: ['error', 'log', 'warn']
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建日志输出函数
|
||||
*/
|
||||
static create(level: 'log' | 'warn' | 'error', styleColor: string, title: string, titleColor = '#fff') {
|
||||
if (this.setting.filter.indexOf(level) == -1) {
|
||||
return empty;
|
||||
}
|
||||
|
||||
if (DEV) {
|
||||
return window.console[level].bind(window.console,
|
||||
'%c %s %c %s ',
|
||||
`background:${styleColor}; padding: 2px; border-radius: 5px 0 0 5px; border: 1px solid ${styleColor}; color: ${titleColor}; font-weight: normal;`,
|
||||
`${title} ${new Date().toLocaleString()}`,
|
||||
`background:#ffffff ; padding: 2px; border-radius: 0 5px 5px 0; border: 1px solid ${styleColor}; color: ${styleColor}; font-weight: normal;`
|
||||
);
|
||||
}
|
||||
return window.console[level].bind(window.console,
|
||||
`${title} [${new Date().toLocaleString()}]`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于输出一般信息
|
||||
*/
|
||||
get log() {
|
||||
return Logger.create('log', '#6495ed', '[LOG]', '#000') as ILog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于输出警告信息
|
||||
*/
|
||||
|
||||
get warn() {
|
||||
return Logger.create('warn', '#ff7f50', '[WARN]', '#000') as ILog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于输出错误信息
|
||||
*/
|
||||
get error() {
|
||||
return Logger.create('error', '#ff4757', '[ERROR]', '#000') as ILog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于输出调试信息
|
||||
*/
|
||||
get debug() {
|
||||
return Logger.create('log', '#ff6347', '[DEBUG]', '#000') as ILog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于输出成功信息
|
||||
*/
|
||||
get success() {
|
||||
return Logger.create('log', '#00ae9d', '[SUCC]', '#000') as ILog;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Logger();
|
||||
9
extensions/app/assets/lib/logger/logger.ts.meta
Normal file
9
extensions/app/assets/lib/logger/logger.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "0b5812e8-b67d-4ba9-83d8-12ca1e46cfd0",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
extensions/app/assets/lib/storage.meta
Normal file
12
extensions/app/assets/lib/storage.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "0c157f59-fd16-449c-b42c-d0efa2dc1401",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
236
extensions/app/assets/lib/storage/storage.ts
Normal file
236
extensions/app/assets/lib/storage/storage.ts
Normal file
@@ -0,0 +1,236 @@
|
||||
import { error, js, log, sys } from 'cc';
|
||||
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
|
||||
function encode(text: string, key: string) {
|
||||
key = key || chars;
|
||||
let encrypted = '';
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length);
|
||||
encrypted += String.fromCharCode(charCode);
|
||||
}
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
function decode(encryptedText: string, key: string) {
|
||||
key = key || chars;
|
||||
let decrypted = '';
|
||||
for (let i = 0; i < encryptedText.length; i++) {
|
||||
const charCode = encryptedText.charCodeAt(i) ^ key.charCodeAt(i % key.length);
|
||||
decrypted += String.fromCharCode(charCode);
|
||||
}
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
const weekOfYear = function (curDate?: Date) {
|
||||
/*
|
||||
date1是当前日期
|
||||
date2是当年第一天
|
||||
d是当前日期是今年第多少天
|
||||
用d + 当前年的第一天的周差距的和在除以7就是本年第几周
|
||||
*/
|
||||
curDate = curDate || new Date();
|
||||
let a = curDate.getFullYear();
|
||||
let b = curDate.getMonth() + 1;
|
||||
let c = curDate.getDate();
|
||||
|
||||
let date1 = new Date(a, b - 1, c), date2 = new Date(a, 0, 1),
|
||||
d = Math.round((date1.valueOf() - date2.valueOf()) / 86400000);
|
||||
return Math.ceil(
|
||||
(d + ((date2.getDay() + 1) - 1)) / 7
|
||||
);
|
||||
};
|
||||
|
||||
const getWeekUpdateTime = function () {
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const week = weekOfYear(date);
|
||||
return year + '' + week;
|
||||
};
|
||||
|
||||
const getDayUpdateTime = function (curDate?: Date) {
|
||||
curDate = curDate || new Date();
|
||||
return curDate.toLocaleDateString();
|
||||
};
|
||||
|
||||
export class Storage {
|
||||
static setting: {
|
||||
/**
|
||||
* 加密密钥
|
||||
* - 如果需要加密内容,请设置密钥的值
|
||||
*/
|
||||
secretKey: string
|
||||
} = {
|
||||
secretKey: ''
|
||||
};
|
||||
|
||||
private _cache = {};
|
||||
|
||||
/**
|
||||
* 返回值为false代表调用失败
|
||||
*/
|
||||
set(key: string, value: unknown) {
|
||||
if (typeof key === 'string' && typeof value !== 'undefined') {
|
||||
try {
|
||||
const data = JSON.stringify(value);
|
||||
if (Storage.setting.secretKey) {
|
||||
sys.localStorage.setItem(key, encode(data, Storage.setting.secretKey));
|
||||
} else {
|
||||
sys.localStorage.setItem(key, data);
|
||||
}
|
||||
// 设置缓存
|
||||
this._cache[key] = data;
|
||||
return true;
|
||||
} catch (err) { log(err); }
|
||||
} else {
|
||||
error('storage set error');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回值为undefined代表调用失败
|
||||
*/
|
||||
get(key: string) {
|
||||
// 先读取缓存
|
||||
if (typeof this._cache[key] !== 'undefined') {
|
||||
return JSON.parse(this._cache[key]);
|
||||
}
|
||||
|
||||
let result = null;
|
||||
try {
|
||||
let data = sys.localStorage.getItem(key);
|
||||
if (data && typeof data === 'string') {
|
||||
if (Storage.setting.secretKey) data = decode(data, Storage.setting.secretKey);
|
||||
// 设置缓存
|
||||
this._cache[key] = data;
|
||||
result = JSON.parse(data);
|
||||
} else if (data !== '' && data !== null) {
|
||||
result = undefined;
|
||||
}
|
||||
} catch (e) {
|
||||
result = undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回值为false代表调用失败
|
||||
*/
|
||||
add(key: string, value: number = 1) {
|
||||
let result = this.get(key);
|
||||
if (result !== undefined) {
|
||||
result = result || 0;
|
||||
result += value;
|
||||
if (this.set(key, result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回值为false代表调用失败
|
||||
*/
|
||||
remove(key: string) {
|
||||
try {
|
||||
sys.localStorage.removeItem(key);
|
||||
delete this._cache[key];
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回值为false代表调用失败
|
||||
*/
|
||||
clear() {
|
||||
try {
|
||||
sys.localStorage.clear();
|
||||
js.clear(this._cache);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置本周数据 [返回值为false代表调用失败]
|
||||
* @param {Function} cb 当已存在本周的数据时,会根据cb的返回决定是否存储,true代表存储
|
||||
*/
|
||||
setWeek(key: string, value: unknown, cb?: (oldValue: unknown, newValue: unknown) => boolean) {
|
||||
const updateTime = getWeekUpdateTime();
|
||||
|
||||
if (cb) {
|
||||
const data = this.getWeek(key);
|
||||
if (data !== undefined) {
|
||||
if (data === null || cb(data, value)) {
|
||||
return this.set(key, {
|
||||
data: value,
|
||||
updateTime: updateTime
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return this.set(key, {
|
||||
data: value,
|
||||
updateTime: updateTime
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本周数据 [返回值为undefined代表调用失败]
|
||||
*/
|
||||
getWeek(key: string) {
|
||||
const data = this.get(key);
|
||||
if (data && data.updateTime == getWeekUpdateTime()) {
|
||||
return data.data;
|
||||
}
|
||||
return data && null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置本天数据 [返回值为false代表调用失败]
|
||||
* @param {Function} cb 当已存在本天的数据时,会根据cb的返回决定是否存储,true代表存储
|
||||
*/
|
||||
setDay(key: string, value: unknown, cb?: (oldValue: unknown, newValue: unknown) => boolean) {
|
||||
const updateTime = getDayUpdateTime();
|
||||
|
||||
if (cb) {
|
||||
const data = this.getDay(key);
|
||||
if (data !== undefined) {
|
||||
if (data === null || cb(data, value)) {
|
||||
return this.set(key, {
|
||||
data: value,
|
||||
updateTime: updateTime
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return this.set(key, {
|
||||
data: value,
|
||||
updateTime: updateTime
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本天数据 [返回值为undefined代表调用失败]
|
||||
* @param {*} key
|
||||
*/
|
||||
getDay(key: string) {
|
||||
const data = this.get(key);
|
||||
if (data && data.updateTime == getDayUpdateTime()) {
|
||||
return data.data;
|
||||
}
|
||||
return data && null;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Storage();
|
||||
9
extensions/app/assets/lib/storage/storage.ts.meta
Normal file
9
extensions/app/assets/lib/storage/storage.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "be3da7ca-1bb5-4a41-894b-f82751c78ef2",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
extensions/app/assets/lib/task.meta
Normal file
12
extensions/app/assets/lib/task.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "54e30e53-aef2-4e16-8969-e38bea0ea336",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
440
extensions/app/assets/lib/task/task.ts
Normal file
440
extensions/app/assets/lib/task/task.ts
Normal file
@@ -0,0 +1,440 @@
|
||||
interface IHandle {
|
||||
(next: (data?: any) => boolean, retry: (timeout?: number) => Promise<boolean>, end: (data?: any) => boolean): void
|
||||
}
|
||||
|
||||
interface IFinish<T> {
|
||||
(results?: T, success?: boolean): any
|
||||
}
|
||||
|
||||
export interface ITask<T extends Array<any> = any[]> {
|
||||
readonly results: Readonly<T>;
|
||||
size(): number;
|
||||
add(handle: IHandle): this;
|
||||
start(finish?: IFinish<T> | Function): this;
|
||||
stop(): boolean;
|
||||
isRunning(): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 顺序执行
|
||||
*/
|
||||
export class Sync<T extends Array<any>> implements ITask<T> {
|
||||
private running = false;
|
||||
private index: number = -1;
|
||||
private list: IHandle[] = [];
|
||||
private finish: IFinish<T> | Function = null;
|
||||
|
||||
/**
|
||||
* 每个handle的返回值,通过next或end存储
|
||||
*/
|
||||
public results: T = [] as T;
|
||||
|
||||
/**
|
||||
* 任务数量
|
||||
* @returns
|
||||
*/
|
||||
public size(): number {
|
||||
return this.list.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个任务
|
||||
* @param handle
|
||||
* @returns
|
||||
*/
|
||||
public add(handle: IHandle) {
|
||||
this.list.push(handle);
|
||||
this.results.push(undefined);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行所有任务
|
||||
* @param finish 执行完毕回调
|
||||
* @returns
|
||||
*/
|
||||
public start(finish?: IFinish<T> | Function) {
|
||||
if (this.running) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.running = true;
|
||||
this.index = -1;
|
||||
this.finish = finish;
|
||||
|
||||
this.next(this.index);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止所有任务
|
||||
* @returns
|
||||
*/
|
||||
public stop(): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.running = false;
|
||||
if (this.finish) {
|
||||
this.finish(this.results, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否正在执行
|
||||
* @returns
|
||||
*/
|
||||
public isRunning() {
|
||||
return this.running;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @returns
|
||||
*/
|
||||
public isStop() {
|
||||
return !this.running;
|
||||
}
|
||||
|
||||
private end(data?: any): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof data !== 'undefined') {
|
||||
this.results[this.index] = data;
|
||||
}
|
||||
|
||||
this.running = false;
|
||||
if (this.finish) {
|
||||
this.finish(this.results, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private next(index: number, data?: any): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index !== this.index) return false;
|
||||
|
||||
if (typeof data !== 'undefined') {
|
||||
this.results[this.index] = data;
|
||||
}
|
||||
|
||||
if (++this.index < this.list.length) {
|
||||
this.retry(this.index);
|
||||
} else {
|
||||
this.end();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private retry(index: number): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index !== this.index) return false;
|
||||
|
||||
const handle = this.list[index];
|
||||
handle && handle(
|
||||
(data?: any) => this.next(index, data),
|
||||
(timeout = 0) => {
|
||||
return new Promise(resolve => {
|
||||
if (timeout > 0) {
|
||||
setTimeout(() => {
|
||||
resolve(this.retry(index));
|
||||
}, timeout * 1000);
|
||||
} else {
|
||||
resolve(this.retry(index));
|
||||
}
|
||||
});
|
||||
},
|
||||
(data?: any) => this.end(data)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同时执行
|
||||
*/
|
||||
export class ASync<T extends Array<any>> implements ITask<T> {
|
||||
private running = false;
|
||||
private count: number = 0;
|
||||
private list: IHandle[] = [];
|
||||
private finish: IFinish<T> | Function = null;
|
||||
|
||||
/**
|
||||
* 每个handle的返回值,通过next或end存储
|
||||
*/
|
||||
public results: T = [] as T;
|
||||
|
||||
/**
|
||||
* 任务数量
|
||||
* @returns
|
||||
*/
|
||||
public size(): number {
|
||||
return this.list.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个任务
|
||||
* @param handle
|
||||
* @returns
|
||||
*/
|
||||
public add(handle: IHandle) {
|
||||
this.list.push(handle);
|
||||
this.results.push(undefined);
|
||||
|
||||
if (this.running) {
|
||||
this.retry(this.list.length - 1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行所有任务
|
||||
* @param finish 执行完毕回调
|
||||
* @returns
|
||||
*/
|
||||
public start(finish?: IFinish<T> | Function) {
|
||||
if (this.running) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.running = true;
|
||||
this.count = 0;
|
||||
this.finish = finish;
|
||||
|
||||
if (this.list.length) {
|
||||
for (let index = 0; index < this.list.length; index++) {
|
||||
this.retry(index);
|
||||
}
|
||||
} else {
|
||||
this.end && this.end(this.count);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止所有任务
|
||||
* @returns
|
||||
*/
|
||||
public stop(): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
this.running = false;
|
||||
if (this.finish) {
|
||||
this.finish(this.results, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否正在执行
|
||||
* @returns
|
||||
*/
|
||||
public isRunning() {
|
||||
return this.running;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @returns
|
||||
*/
|
||||
public isStop() {
|
||||
return !this.running;
|
||||
}
|
||||
|
||||
private end(index: number, data?: any): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index >= 0 && index < this.results.length) {
|
||||
if (this.results[index] || this.results[index] === null) return false;
|
||||
this.results[index] = typeof data !== 'undefined' ? data : null;
|
||||
}
|
||||
|
||||
this.running = false;
|
||||
if (this.finish) {
|
||||
this.finish(this.results, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private next(index: number, data?: any): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index >= 0 && index < this.results.length) {
|
||||
if (this.results[index] || this.results[index] === null) return false;
|
||||
this.results[index] = typeof data !== 'undefined' ? data : null;
|
||||
}
|
||||
|
||||
if (++this.count === this.list.length) {
|
||||
this.end && this.end(this.count);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private retry(index: number): boolean {
|
||||
if (!this.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const handle = this.list[index];
|
||||
handle && handle(
|
||||
(data?: any) => this.next(index, data),
|
||||
(timeout = 0) => {
|
||||
return new Promise(resolve => {
|
||||
if (timeout > 0) {
|
||||
setTimeout(() => {
|
||||
resolve(this.retry(index));
|
||||
}, timeout * 1000);
|
||||
} else {
|
||||
resolve(this.retry(index));
|
||||
}
|
||||
});
|
||||
},
|
||||
(data?: any) => this.end(index, data)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class Any<T extends Array<any>> implements ITask<T> {
|
||||
private task = new Sync();
|
||||
|
||||
/**
|
||||
* 每个handle的返回值,通过next或end存储
|
||||
*/
|
||||
public get results(): T {
|
||||
return this.task.results as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务数量
|
||||
* @returns
|
||||
*/
|
||||
public size() {
|
||||
return this.task.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个任务
|
||||
* @param handle
|
||||
* @returns
|
||||
*/
|
||||
public add(handles: IHandle | IHandle[]) {
|
||||
if (handles instanceof Array) {
|
||||
const async = new ASync();
|
||||
handles.forEach(handle => async.add(handle));
|
||||
this.task.add(async.start.bind(async));
|
||||
} else {
|
||||
this.task.add(handles);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行所有任务
|
||||
* @param finish 执行完毕回调
|
||||
* @returns
|
||||
*/
|
||||
public start(finish?: IFinish<T> | Function) {
|
||||
this.task.start(finish);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止所有任务
|
||||
* @returns
|
||||
*/
|
||||
public stop() {
|
||||
return this.task.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否正在执行
|
||||
* @returns
|
||||
*/
|
||||
public isRunning() {
|
||||
return this.task.isRunning();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @returns
|
||||
*/
|
||||
public isStop() {
|
||||
return this.task.isStop();
|
||||
}
|
||||
}
|
||||
|
||||
interface IExecuteCallBack {
|
||||
(retry: (timeout?: number) => void): void
|
||||
}
|
||||
|
||||
const task = {
|
||||
/**
|
||||
* 任务顺序执行
|
||||
*/
|
||||
createSync<T extends Array<any>>(): Sync<T> {
|
||||
return new Sync<T>();
|
||||
},
|
||||
|
||||
/**
|
||||
* 任务同时执行
|
||||
*/
|
||||
createASync<T extends Array<any>>(): ASync<T> {
|
||||
return new ASync<T>();
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据参数指定执行顺序
|
||||
* @example
|
||||
* createAny()
|
||||
* .add(1).add(2).add(3).add(4)
|
||||
* .add([5,6,7])
|
||||
* .add(8)
|
||||
* 执行顺序,1,2,3,4依次执行,然后同时执行5,6,7,最后执行8
|
||||
*/
|
||||
createAny<T extends Array<any>>() {
|
||||
return new Any<T>();
|
||||
},
|
||||
|
||||
/**
|
||||
* 执行单个任务
|
||||
*/
|
||||
execute(fun: IExecuteCallBack, retryMax = -1, retryFinish?: Function) {
|
||||
fun(function retry(timeout = 0) {
|
||||
if (retryMax === 0) return retryFinish && retryFinish();
|
||||
retryMax = retryMax > 0 ? retryMax - 1 : retryMax;
|
||||
if (timeout > 0) {
|
||||
setTimeout(() => task.execute(fun, retryMax, retryFinish), timeout * 1000);
|
||||
} else {
|
||||
task.execute(fun, retryMax, retryFinish);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default task;
|
||||
9
extensions/app/assets/lib/task/task.ts.meta
Normal file
9
extensions/app/assets/lib/task/task.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "721e6dcc-aab3-48d6-aa4e-e1baf821263b",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user