详解CocosCreator消息分发机制


Posted in Javascript onApril 16, 2021

概述

本篇开始介绍游戏业务架构相关的内容。在游戏业务层,所有需要隔离的系统和模块间通信都可以通过消息分发解耦。例如网络返回通知、数据更新同步到界面等。

消息分发基于观察者模式设计。需要处理消息的地方向消息中心注册监听回调,派发消息时,调用消息中心的派发接口遍历该消息的监听队列,调用对应的回调方法。

具体方案

先定义监听回调类型

/**
 * 消息监听回调方法
 */
export type NotifyListener = (src: any, data: any) => void;

通过key-value方式保存监听队列

private static msg2listDict: Dictionary< string, Array<NotifyListenerInfo> > = new Dictionary< string, Array<NotifyListenerInfo> >();

接口定义

/**
 * 添加多次监听者,需要手动移除
 * @param msg
 * @param listener
 * @param target
 */
public static addListener(msg: string, listener: NotifyListener, target?: any): void {}
 
/**
 * 添加单次监听者,事件触发后即移除
 * @param msg
 * @param listener
 * @param target
 */
public static addOnceListener(msg: string, listener: NotifyListener, target?: any): void {}
 
/**
 * 移除指定消息指定的监听者
 * @param msg
 * @param listener
 */
public static removeMsgListener(msg: string, listener: NotifyListener): void {}
 
/**
 * 移除指定消息所有监听者
 * @param msg
 */
public static removeMsgAllListeners(msg: string): void {}
 
/**
 * 移除指定目标对指定消息的监听
 * @param msg
 * @param target
 */
public static removeTargetMsgListen(msg: string, target: any): void {}
 
/**
 * 移除指定目标所有消息监听
 * @param target
 */
public static removeTargetAllMsgListen(target: any): void {}
 
/**
 * 派发消息
 * @param msg
 * @param src
 * @param data
 */
public static notify(msg: string, src: any, data: any): void {}

在添加移除实现中,需要注意某消息可能正在派发。

对于一个消息新添加的监听者,应该在当前队列消息派发完后再派发,因此,添加一个待添加队列

private static listener2add: Array<NotifyListenerInfo> = [];

在添加监听者时做以下判断

// 该消息正在派发,放入待添加队列
if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
    NotifyCenter.listener2add.push(info);
    return;
}

同样在移除监听者时,可能正在派发消息,避免对队列的修改导致for循环异常,添加一个待移除队列,派发消息时,如果该监听者在移除队列则不派发。在消息派发完后再将其移出队列

private static listener2remove: Array<NotifyListenerInfo> = [];

在移除监听者时做以下判断

// 该消息正在派发,放入待移除队列
if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
    NotifyCenter.listener2remove.push(list[i]);
} else {
    list.splice(i, 1);
}

派发消息时遍历指定消息下的队列

// 队列不存在,不需要处理
let list = NotifyCenter.msg2listDict.get(msg);
if (!list) {
    return;
}
 
// 标记消息正在派发,多个消息可能同时在派发,同一消息可能标记多次
NotifyCenter.notifyMsgs.push(msg);
 
// 处理消息派发
for (let i = 0, n = list.length; i < n; i++) {
    NotifyCenter._dispatch(list[i], src, data, false);
}

派发消息时先判断是否在移除队列

// 在移除队列,不派发
if (NotifyCenter.listener2remove.indexOf(info) >= 0) {
    return;
}

当前队列派发完后检查待添加队列

// 处理待添加队列派发
for (let i = 0, n = msg2add.length; i < n; i++) {
    if (listener2add[i].msg == msg) {
        NotifyCenter._dispatch(listener2add[i], src, data, true);
    }
}

引入消息分发中心,隔离的系统、模块间通过消息监听和派发通信,避免互相引用耦合。

以上就是详解CocosCreator消息分发机制的详细内容,更多关于CocosCreator消息分发的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JS 页面内容搜索,类似于 Ctrl+F功能的实现代码
Aug 13 Javascript
实现图片预加载的三大方法及优缺点分析
Nov 19 Javascript
jQuery绑定事件的几种实现方式
May 09 Javascript
浅析Bootstrip的select控件绑定数据的问题
May 10 Javascript
利用Js+Css实现折纸动态导航效果实例源码
Jan 25 Javascript
BetterScroll 在移动端滚动场景的应用
Sep 18 Javascript
bootstrap响应式工具使用详解
Nov 29 Javascript
swiper 自动图片无限轮播实现代码
May 21 Javascript
JSX在render函数中的应用详解
Sep 04 Javascript
electron-vue开发环境内存泄漏问题汇总
Oct 10 Javascript
如何通过JS实现转码与解码
Feb 21 Javascript
解决vue项目获取dom元素宽高总是不准确问题
Jul 29 Javascript
CocosCreator入门教程之网络通信
Apr 16 #Javascript
JavaScript嵌入百度地图API的最详细方法
用javascript制作qq注册动态页面
利用javaScript处理常用事件详解
Apr 14 #Javascript
带你彻底理解JavaScript中的原型对象
Apr 14 #Javascript
游戏开发中如何使用CocosCreator进行音效处理
详解CocosCreator项目结构机制
You might like
sphinx增量索引的一个问题
2011/06/14 PHP
解析php多线程下载远程多个文件
2013/06/25 PHP
PHP对表单提交特殊字符的过滤和处理方法汇总
2014/02/18 PHP
ThinkPHP进程计数类Process用法实例详解
2015/09/25 PHP
利用jQuery实现可输入搜索文字的下拉框
2013/10/23 Javascript
Javascript中string转date示例代码
2013/11/01 Javascript
a标签的href与onclick事件的区别详解
2014/11/12 Javascript
jQuery 常用代码集锦(必看篇)
2016/05/16 Javascript
Vuex之理解Getters的用法实例
2017/04/19 Javascript
AngularJS中使用ngModal模态框实例
2017/05/27 Javascript
vue+vue-router转场动画的实例代码
2018/09/01 Javascript
vue项目中锚点定位替代方式
2019/11/13 Javascript
如何优雅地取消 JavaScript 异步任务
2020/03/22 Javascript
jQuery HTML css()方法与css类实例详解
2020/05/20 jQuery
Vue中父子组件的值传递与方法传递
2020/09/28 Javascript
解决pycharm双击但是无法打开的情况
2020/10/31 Javascript
在Python的Flask中使用WTForms表单框架的基础教程
2016/06/07 Python
matplotlib中legend位置调整解析
2017/12/19 Python
对python 通过ssh访问数据库的实例详解
2019/02/19 Python
python使用adbapi实现MySQL数据库的异步存储
2019/03/19 Python
Windows下Anaconda和PyCharm的安装与使用详解
2020/04/23 Python
python 使用raw socket进行TCP SYN扫描实例
2020/05/05 Python
python 实现数据库中数据添加、查询与更新的示例代码
2020/12/07 Python
matplotlib相关系统目录获取方式小结
2021/02/03 Python
python 统计list中各个元素出现的次数的几种方法
2021/02/20 Python
中国排名第一的外贸销售网站:LightInTheBox.com(兰亭集势)
2016/10/28 全球购物
什么是serialVersionUID
2016/03/04 面试题
.NET里面如何取得当前的屏幕分辨率
2012/12/06 面试题
软件测试常见笔试题
2012/02/04 面试题
实习生自我评价
2014/01/18 职场文书
建筑安全员岗位职责
2014/03/13 职场文书
班级光棍节联谊会策划书
2014/10/10 职场文书
人身损害赔偿协议书格式
2014/11/01 职场文书
二审代理词范文
2015/05/25 职场文书
电影雨中的树观后感
2015/06/15 职场文书
Vue提供的三种调试方式你知道吗
2022/01/18 Vue.js