ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

TypeScript之多方法执行方案

2020-08-28 07:02:17  阅读:221  来源: 互联网

标签:方案 TypeScript sender list tag ._ 之多 exeParams data


一, 情景

①,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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有