其他分享
首页 > 其他分享> > TypeScript之多方法执行方案

TypeScript之多方法执行方案

作者:互联网

一, 情景

①,A,B,C,D四个方法都执行完毕之后再执行E方法
②,A,B,C,D四个方法有其中任意一个执行完毕后再执行E方法

注意: A、B,C,D 可以是普通方法, 也可以是异步方法 ,可以带参数, 也可以没有参数

二,解决方案

①,BaseMultiFunctionExecute.ts (对方法执行基类)

/**
 * 多方法执行基类
 * @author  Husz
 */
abstract class BaseMultiFunctionExecute<T extends IMultiFunctionData>{
    protected _list: Array<T>;
    protected _callback: (tag: string, sender: any, ...arg) => void;
    protected _mgrCb: (tag: string, sender: any, ...arg) => void;
    protected _isExeing: boolean = false;//是否正在处理中
    protected _curIndex: number;
    protected _inPool: boolean = false;
    protected _tag: string;

    /**
     * 是否在对象池
     */
    public set InPool(value: boolean) {
        this._inPool = value;
    }

    /**
     * 是否在对象池
     */
    public get InPool(): boolean {
        return this._inPool;
    }

    public constructor(tag: string, list: Array<{ exeFun: Function, sender: any, isPromise?: boolean, exeParams?: Array<any> }>, callback: (tag: string, sender: any, ...arg) => void, mgrCb: (tag: string, sender: any, ...arg) => void) {
        this._mgrCb = mgrCb;
        this.resetData(tag, list, callback);
    }

    /**
     *  获取类型
     */
    public abstract getType(): Ty2MultiFunctions;
    /**
     * 重置数据
     */
    public resetData(tag: string, list: Array<{ exeFun: Function, sender: any, isPromise?: boolean, exeParams?: Array<any> }>, callback: (tag: string, sender: any, ...arg) => void): void {
        if (this._inPool) return;
        this._tag = tag;
        this._list = this.getList(list);
        this._callback = callback;
    }

    /**
     * 获取list数据
     */
    protected getList(list: Array<{ exeFun: Function, sender: any, isPromise?: boolean, exeParams?: Array<any> }>): Array<T> {
        if (list == null || list.length == 0) return [];
        let cell: { exeFun: Function, sender: any, isPromise?: boolean, exeParams?: Array<any> };
        let bc: Array<T> = [];
        for (let i: number = 0, j: number = list.length; i < j; i++) {
            cell = list[i];
            bc.push(<T><any>{
                exeFun: cell.exeFun,
                sender: cell.sender,
                isPromise: cell.isPromise != null ? cell.isPromise : false,
                isSucc: false,
                exeParams: cell.exeParams == null || cell.exeParams.length < 0 ? null : cell.exeParams,
                complete: false
            });
        }
        return bc;
    }

    /**
     * @return 是否添加成功
     */
    public addItem(cell: { exeFun: Function, sender: any, isPromise?: boolean, exeParams?: Array<any> }): boolean {
        if (this._isExeing || !cell || this._inPool) return false;
        let data: T = <T><any>{
            exeFun: cell.exeFun,
            sender: cell.sender,
            isPromise: cell.isPromise != null ? cell.isPromise : false,
            isSucc: false,
            exeParams: cell.exeParams == null || cell.exeParams.length < 0 ? null : cell.exeParams,
            complete: false
        };
        if (this._list) {
            this._list.push(data);
        } else {
            this._list = [data];
        }
        return true;
    }

    /**
     * 开始处理数据(入口)
     */
    public async startExe(): Promise<void> {
        return new Promise<void>(resolve => {
            if( this._isExeing || this._inPool){
                resolve();
                return;
            }
            if (this._list == null || this._list.length == 0 ) {
                this._callback(`exe_complete`, this, this._tag);
                this._mgrCb(`over`, this, this._tag);
                resolve();
            } else {
                this.exeFunctions();
                resolve();
            }
        });
    }

    /**
     * 执行方法
     */
    protected exeFunctions(): void {
        this._isExeing = true;
        this._curIndex = 0;
    }

    /**
     * 检测是否已经做完
     * @param data
     */
    protected checkOver(data: T, isSucc: boolean): void {
        data.complete = true;
        data.isSucc = isSucc;
        this.addCopletaTag();
    }

    /**
     * 处理完成计数
     */
    protected addCopletaTag(): void {
        this._curIndex++;
        if (this._curIndex >= this._list.length) {
            this._callback(`exe_complete`, this, this._tag);
            this._mgrCb(`over`, this);
        }
    }

    /**
     * 清理
     */
    public clear(): void {
        this._isExeing = false;
        this._list = null;
        this._inPool = true;
    }

    /**
     * @return { complete: 是否执行完毕, isSucc: 是否执行成功 }
     */
    public isFunComplete(exeFun: Function): { complete: boolean, isSucc: boolean } {
        if (!this._list || this._list.length == 0 || this._inPool) return { complete: false, isSucc: false };
        let data: T;
        for (let i: number = 0, j: number = this._list.length; i < j; i++) {
            data = this._list[i];
            if (data.exeFun == exeFun) {
                if (data.complete == null && data.complete == false) {
                    return { complete: false, isSucc: false };
                } else {
                    return { complete: true, isSucc: data.isSucc }
                }
            }
        }
        return { complete: false, isSucc: false };
    }

    /**
     * 销毁
     */
    public destroy(): void {
        this._callback = null;
        this._list = null;
        this._mgrCb = null;
    }
}

/**
 * 多方法执行单元数据
 * @author  Husz
 */
interface IMultiFunctionData {
    exeFun: Function;
    sender: any;
    complete?: boolean;
    exeParams?: Array<any>;
    isPromise: boolean;//是否是异步方法
    isSucc?: boolean;//是否执行成功
}

②,TogetherExecute.ts (全部执行完毕后执行E 子类)

/**
 * 全部执行
 * @author Husz
 */
class TogetherExecute extends BaseMultiFunctionExecute<IMultiFunctionData>{
    /**
     * @inheritDoc
     */
    protected exeFunctions(): void {
        super.exeFunctions();
        this.stepDoFunctions(this._curIndex);
    }

    /**
     * @inheritDoc
     */
    public getType(): Ty2MultiFunctions {
        return Ty2MultiFunctions.___TOGETHER___;
    }

    /**
     * 处理异步方法
     */
    private doPomise(data: IMultiFunctionData): void {
        if (data.sender != null) {
            data.exeFun.bind(data.sender);
        }
        if (data.exeParams != null && data.exeParams.length > 0) {
            data.exeFun(...data.exeParams).then(() => {
                this.checkOver(data, true);
            }).catch(() => {
                this.checkOver(data, false);
            });
        } else {
            data.exeFun().then(() => {
                this.checkOver(data, true);
            }).catch(() => {
                this.checkOver(data, false);
            });
        }
    }

    /**
     * 分步执行方法
     */
    private stepDoFunctions: (index: number) => void = (index) => {
        if (index < this._list.length) {
            let data: IMultiFunctionData = this._list[index];
            if (data.isPromise) {
                this.doPomise(data);
            } else {
                if (data.sender) {
                    if (data.exeParams != null && data.exeParams.length > 0) {
                        data.exeFun.call(data.sender, ...data.exeParams);
                    } else {
                        data.exeFun.call(data.sender);
                    }
                } else {
                    if (data.exeParams != null && data.exeParams.length > 0) {
                        data.exeFun(...data.exeParams);
                    } else {
                        data.exeFun();
                    }
                }
                this.checkOver(data, true);
            }
            index++;
            this.stepDoFunctions(index);
        }
    };
}

③,OtherExecute.ts (任意方法执行完毕执行E 子类)

/**
 * 其中一个完成
 * @author Husz
 */
class OtherExecute extends BaseMultiFunctionExecute<IMultiFunctionData>{
    /**
     * @inheritDoc
     */
    protected addCopletaTag(): void {
        this._curIndex++;
        if (this._curIndex == 1) {
            this._callback(`exe_complete`, this, this._tag);
        }
        if (this._curIndex >= this._list.length) {
            this._mgrCb(`over`, this); // 通知管理器处理结束
            // this._callback( `all_complete` , this );
        }
    }

    /**
     * @inheritDoc
     */
    public getType(): Ty2MultiFunctions {
        return Ty2MultiFunctions.___OTHER___;
    }

    /**
     * @inheritDoc
     */
    protected exeFunctions(): void {
        super.exeFunctions();
        this.stepDoFunctions(this._curIndex);
    }

    /**
     * 处理异步方法
     */
    private doPomise(data: IMultiFunctionData): void {
        if (data.sender != null) {
            data.exeFun.bind(data.sender);
        }
        if (data.exeParams != null && data.exeParams.length > 0) {
            data.exeFun(...data.exeParams).then(() => {
                this.checkOver(data, true);
            }).catch(() => {
                this.checkOver(data, false);
            });
        } else {
            data.exeFun().then(() => {
                this.checkOver(data, true);
            }).catch(() => {
                this.checkOver(data, false);
            });
        }
    }

    /**
     * 分步执行方法
     */
    private stepDoFunctions: (index: number) => void = (index) => {
        if (index < this._list.length) {
            let data: IMultiFunctionData = this._list[index];
            if (data.isPromise) {
                this.doPomise(data);
            } else {
                if (data.sender) {
                    if (data.exeParams != null && data.exeParams.length > 0) {
                        data.exeFun.call(data.sender, ...data.exeParams);
                    } else {
                        data.exeFun.call(data.sender);
                    }
                } else {
                    if (data.exeParams != null && data.exeParams.length > 0) {
                        data.exeFun(...data.exeParams);
                    } else {
                        data.exeFun();
                    }
                }
                this.checkOver(data, true);
            }
            this.stepDoFunctions(++index);
        }
    };

}

④,MultiFunctionsMgr.ts (多方法执行管理器)

/**
 * 多方法执行管理器
 * @author  Husz
 */
class MultiFunctionsMgr {
    private static _instance: MultiFunctionsMgr;
    public static get Instance(): MultiFunctionsMgr {
        if (!MultiFunctionsMgr._instance)
            MultiFunctionsMgr._instance = new MultiFunctionsMgr();
        return MultiFunctionsMgr._instance;
    }
    private _list: Map<Ty2MultiFunctions, PoolObject<BaseMultiFunctionExecute<any>>>;

    private constructor() {
        this._list = new Map<Ty2MultiFunctions, PoolObject<BaseMultiFunctionExecute<any>>>();
    }

    private createExe(tag: string, ty: Ty2MultiFunctions, list: Array<{ exeFun: Function, sender: any, isPromise?: boolean, exeParams?: Array<any> }>, callback: (tag: string, sender: any, ...arg) => void): BaseMultiFunctionExecute<any> {
        switch (ty) {
            case Ty2MultiFunctions.___TOGETHER___:
                return new TogetherExecute(tag, list, callback, this.onStandardCallback);
            case Ty2MultiFunctions.___OTHER___:
                return new OtherExecute(tag, list, callback, this.onStandardCallback);
        }
    }

    /**
     * 获取执行句柄
     */
    public getExeFun(tag: string, ty: Ty2MultiFunctions, list: Array<{ exeFun: Function, sender: any, isPromise?: boolean, exeParams?: Array<any> }>, callback: (tag: string, sender: any, ...arg) => void): BaseMultiFunctionExecute<any> {
        let cell: BaseMultiFunctionExecute<any>;
        if (this._list.has(ty)) {
            let pool: PoolObject<BaseMultiFunctionExecute<any>>;
            pool = this._list[ty];
            cell = pool.Cell;
            if (!cell) {
                cell = this.createExe(tag, ty, list, callback);
            } else {
                cell.InPool = false;//从对象池中提取出来了
                cell.resetData(tag, list, callback);
            }
        } else {
            cell = this.createExe(tag, ty, list, callback);
        }
        return cell;
    }

    /**
     * 标准回调
     */
    private onStandardCallback: (tag: string, sender: any, ...arg) => void = (tag, sender, ...arg) => {
        switch (tag) {
            case `over`:
                (sender as BaseMultiFunctionExecute<any>).clear();
                let ty: Ty2MultiFunctions = (sender as BaseMultiFunctionExecute<any>).getType();
                let pool: PoolObject<BaseMultiFunctionExecute<any>>;
                if (this._list.has(ty)) {
                    pool = this._list[ty];
                    if (!pool.push(sender)) {
                        (sender as BaseMultiFunctionExecute<any>).destroy();
                    }
                } else {
                    pool = new PoolObject<BaseMultiFunctionExecute<any>>(2);
                    pool.push(sender);
                    this._list.set(ty, pool);
                }
                break;
        }
    };

}

/**
 * 执行类型
 * @author Husz
 */
enum Ty2MultiFunctions {
    ___TOGETHER___ = 1,
    ___OTHER___ = 2
}

三,调用方案

①,回调

    private onStandardCallback: ( tag: string, sender: any,...arg ) => void =  (tag, sender, ...arg) => {
        switch (tag) {
            case `exe_complete`:
                if( arg[0] == `Aonaufly` ){
                    console.log(`lkkkkkk :  -> `);
                }
                break;
        }
    };

②,A,B,C,D方法

    private doA(  ): void{
        console.log(`do a`);
    }

    private doB( a: number , b: number ): void{
        console.log( `do b ${ a + b }` );
    }

    private async doC(): Promise<void>{
        return new Promise<void>( resolve => {
            egret.setTimeout( () => {
                console.log(`do c`);
                resolve();
            } , this, 2000 );
        } );
    }

    private async doD( a: number , b: number ): Promise<void>{
        return new Promise<void>( resolve => {
            egret.setTimeout( () => {
                console.log(`do d ${a + b}`);
                resolve();
            } , this, 2000 );
        } );
    }

③调用

     this.a = MultiFunctionsMgr.Instance.getExeFun(
            `Aonaufly`,
            Ty2MultiFunctions.___TOGETHER___,
            [
                {
                    exeFun: this.doA,
                    sender: this,
                    isPromise: false,
                    exeParams: null
                },
                {
                    exeFun: this.doB,
                    sender: this,
                    isPromise: false,
                    exeParams: [1,2]
                },
                {
                    exeFun: this.doC,
                    sender: this,
                    isPromise: true,
                    exeParams: null
                },
                {
                    exeFun: this.doD,
                    sender: this,
                    isPromise: true,
                    exeParams: [3,4]
                }
            ],
            this.onStandardCallback
            );

            this.a.startExe();

四,执行结果:

TypeScript之多方法执行方案

标签:方案,TypeScript,sender,list,tag,._,之多,exeParams,data
来源: https://blog.51cto.com/aonaufly/2524921