异步全局消息管理器

自己写的一个异步全局消息管理器,也可以叫事件管理器,可以延时执行消息,像网络消息啊、资源加载啊、逻辑定时器啊什么的都可以丢给他,因为写了多年C++所以设计思路都是按C++的来的。

源码:https://gitee.com/jinghuashuiyue2017/GlobalMessage

有兴趣的朋友可以交流一下

1赞

TestScript.js

cc.Class({
    extends: cc.Component,
    properties: {    },
    start () {
        globalMessage.AddListener(111,this.Callback1,this);
        globalMessage.AddListener("222",this.Callback2,this);
    },

    OnButton1()
    {
        cc.log("OnButton1");
        globalMessage.PostMsg(111,0,"111111111111");
    },
    OnButton2()
    {
        cc.log("OnButton2");
        globalMessage.PostMsg("222",3,"22222222222");
    },
    Callback1(msg)
    {
        cc.log(msg.data);
    },
    Callback2(msg)
    {
        cc.log(msg.data);
        globalMessage.DeleteListenerByTarget(111,this);
    }
});

GlobalMessageScript.js

cc.Class({
    extends: cc.Component,
    properties: {  },
    onLoad () { cc.game.addPersistRootNode(this.node); },

    update (dt) { globalMessage.Update(dt); },
});

GlobalMessage.js

window.globalMessage = {
    //自增ID
    msgID: 0,
    //监听者列表
    msgList: [],
    //事件列表
    listenerMap: new Map(),
    //增加消息监听
    AddListener:function(msgType, callback, target){
        //回调对象
        let msgListener = {
            callback: callback,
            target: target,
        };

        let listener = this.listenerMap.get(msgType);
        if (listener!=null) {
            listener.push(msgListener);
        }
        else{
            let arr = new Array(msgListener);
            this.listenerMap.set(msgType, arr);
        }
    },
    //发消息
    PostMsg:function(msgType, time, msgData){
        this.msgID++;
        if (this.msgID > 100000000) {
            this.msgID = 1;
        }
        //事件对象
        var msgEvent = {
            id: this.msgID,
            msgType: msgType,
            data: msgData,
            time: time,//毫秒
        };
        this.msgList.push(msgEvent);
        return this.msgID;
    },
    //更新队列
    Update:function(second){
        if (this.msgList.length > 0) {
            for (let i = 0; i < this.msgList.length; i++) {
                let msg = this.msgList[i];
                msg.time -= second;
                if (msg.time < 0) {
                    let listener = this.listenerMap.get(msg.msgType);
                    if (listener!=null) {
                        for (let j = 0; j < listener.length; j++) {
                            listener[j].callback.call(listener[j].target, msg);
                        }
                    }
                    this.msgList.splice(i, 1);
                    i--;
                }
            }
        }
    },
    //删除一条消息
    DeleteMsg:function(msgID){
        for (let index = 0; index < this.msgList.length;index++) {
            if (this.msgList[index].msgID==msgID) {
                this.msgList.splice(index,1);
                break;
            }
        }
    },
    //删除回调,删除该消息类型的所有回调
    DeleteListenerByType:function(msgType){
        if (this.listenerMap.has(msgType)) {
            this.listenerMap.delete(msgType);
        }
    },
    //删除回调,删除该消息类型的一个回调
    DeleteListenerByTarget:function(msgType, target){
        let listener = this.listenerMap.get(msgType);
        if (listener!=null) {
            for (let index = 0; index < listener.length; index++) {
                if (listener[index].target===target) {
                    listener.splice(index,1);
                    break;
                }
            }
        }
    }
};

替楼主整理了下代码,其实我这里也有和楼主类似的设计,不过设计的要比楼主的更和creator紧凑点,不过也从你的代码中学到了新的思路:sweat_smile:
https://github.com/tidys/CocosCreatorPlugins/blob/master/assets/core/Observer.js
https://github.com/tidys/CocosCreatorPlugins/blob/master/assets/core/ObserverMgr.js

跟cc.game.on/off有啥区别。。。

我也有类似的设计。初步的设计是因为网络延迟,我主要是采用 key - callback的形式存储起来的,比较小巧。关于事件管理的设计,我有一点需求是事件队列。当实时战斗时,切出画面,当回来的时候,事件理应是堆积起来的,然后按照顺序快速播放。

可以给事件加一些属性,比如是否立即处理,还是延迟处理,还是怎么的,有个触发条件,然后存储到一个list里面,然后靠引擎的update驱动事件派发,自己维护一套事件机制,总之,这个还是得看项目需求,实现起来也不算太难:smiley: