詳解CocosCreator消息分發(fā)機(jī)制
概述
本篇開(kāi)始介紹游戲業(yè)務(wù)架構(gòu)相關(guān)的內(nèi)容。在游戲業(yè)務(wù)層,所有需要隔離的系統(tǒng)和模塊間通信都可以通過(guò)消息分發(fā)解耦。例如網(wǎng)絡(luò)返回通知、數(shù)據(jù)更新同步到界面等。
消息分發(fā)基于觀察者模式設(shè)計(jì)。需要處理消息的地方向消息中心注冊(cè)監(jiān)聽(tīng)回調(diào),派發(fā)消息時(shí),調(diào)用消息中心的派發(fā)接口遍歷該消息的監(jiān)聽(tīng)隊(duì)列,調(diào)用對(duì)應(yīng)的回調(diào)方法。
具體方案
先定義監(jiān)聽(tīng)回調(diào)類(lèi)型
/** * 消息監(jiān)聽(tīng)回調(diào)方法 */ export type NotifyListener = (src: any, data: any) => void;
通過(guò)key-value方式保存監(jiān)聽(tīng)隊(duì)列
private static msg2listDict: Dictionary< string, Array<NotifyListenerInfo> > = new Dictionary< string, Array<NotifyListenerInfo> >();
接口定義
/**
* 添加多次監(jiān)聽(tīng)者,需要手動(dòng)移除
* @param msg
* @param listener
* @param target
*/
public static addListener(msg: string, listener: NotifyListener, target?: any): void {}
/**
* 添加單次監(jiān)聽(tīng)者,事件觸發(fā)后即移除
* @param msg
* @param listener
* @param target
*/
public static addOnceListener(msg: string, listener: NotifyListener, target?: any): void {}
/**
* 移除指定消息指定的監(jiān)聽(tīng)者
* @param msg
* @param listener
*/
public static removeMsgListener(msg: string, listener: NotifyListener): void {}
/**
* 移除指定消息所有監(jiān)聽(tīng)者
* @param msg
*/
public static removeMsgAllListeners(msg: string): void {}
/**
* 移除指定目標(biāo)對(duì)指定消息的監(jiān)聽(tīng)
* @param msg
* @param target
*/
public static removeTargetMsgListen(msg: string, target: any): void {}
/**
* 移除指定目標(biāo)所有消息監(jiān)聽(tīng)
* @param target
*/
public static removeTargetAllMsgListen(target: any): void {}
/**
* 派發(fā)消息
* @param msg
* @param src
* @param data
*/
public static notify(msg: string, src: any, data: any): void {}
在添加移除實(shí)現(xiàn)中,需要注意某消息可能正在派發(fā)。
對(duì)于一個(gè)消息新添加的監(jiān)聽(tīng)者,應(yīng)該在當(dāng)前隊(duì)列消息派發(fā)完后再派發(fā),因此,添加一個(gè)待添加隊(duì)列
private static listener2add: Array<NotifyListenerInfo> = [];
在添加監(jiān)聽(tīng)者時(shí)做以下判斷
// 該消息正在派發(fā),放入待添加隊(duì)列
if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
NotifyCenter.listener2add.push(info);
return;
}
同樣在移除監(jiān)聽(tīng)者時(shí),可能正在派發(fā)消息,避免對(duì)隊(duì)列的修改導(dǎo)致for循環(huán)異常,添加一個(gè)待移除隊(duì)列,派發(fā)消息時(shí),如果該監(jiān)聽(tīng)者在移除隊(duì)列則不派發(fā)。在消息派發(fā)完后再將其移出隊(duì)列
private static listener2remove: Array<NotifyListenerInfo> = [];
在移除監(jiān)聽(tīng)者時(shí)做以下判斷
// 該消息正在派發(fā),放入待移除隊(duì)列
if (NotifyCenter.notifyMsgs.indexOf(msg) >= 0) {
NotifyCenter.listener2remove.push(list[i]);
} else {
list.splice(i, 1);
}
派發(fā)消息時(shí)遍歷指定消息下的隊(duì)列
// 隊(duì)列不存在,不需要處理
let list = NotifyCenter.msg2listDict.get(msg);
if (!list) {
return;
}
// 標(biāo)記消息正在派發(fā),多個(gè)消息可能同時(shí)在派發(fā),同一消息可能標(biāo)記多次
NotifyCenter.notifyMsgs.push(msg);
// 處理消息派發(fā)
for (let i = 0, n = list.length; i < n; i++) {
NotifyCenter._dispatch(list[i], src, data, false);
}
派發(fā)消息時(shí)先判斷是否在移除隊(duì)列
// 在移除隊(duì)列,不派發(fā)
if (NotifyCenter.listener2remove.indexOf(info) >= 0) {
return;
}
當(dāng)前隊(duì)列派發(fā)完后檢查待添加隊(duì)列
// 處理待添加隊(duì)列派發(fā)
for (let i = 0, n = msg2add.length; i < n; i++) {
if (listener2add[i].msg == msg) {
NotifyCenter._dispatch(listener2add[i], src, data, true);
}
}
引入消息分發(fā)中心,隔離的系統(tǒng)、模塊間通過(guò)消息監(jiān)聽(tīng)和派發(fā)通信,避免互相引用耦合。
以上就是詳解CocosCreator消息分發(fā)機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于CocosCreator消息分發(fā)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
悄悄用腳本檢查你訪問(wèn)過(guò)哪些網(wǎng)站的代碼
YouPorn是YouTube的成人自拍版,Alexa排名61。如果你登陸YouPorn主頁(yè),它會(huì)悄悄用腳本檢查你訪問(wèn)過(guò)哪些色情網(wǎng)站。2010-12-12
JavaScript將數(shù)組轉(zhuǎn)換為鏈表的方法
這篇文章主要介紹了JavaScript將數(shù)組轉(zhuǎn)換為鏈表的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
js+springMVC 提交數(shù)組數(shù)據(jù)到后臺(tái)的實(shí)例
今天小編就為大家分享一篇js+springMVC 提交數(shù)組數(shù)據(jù)到后臺(tái)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
讓ie6也支持websocket采用flash封裝實(shí)現(xiàn)
ie9都不支持websocket,何況ie6,往往這些不可思議的事情卻意想不到的發(fā)生了;websocket能開(kāi)發(fā)那么酷的功能,怎么能讓ie攔住我們的腳步,用falsh封裝吧,感興趣的你可不要錯(cuò)過(guò)了哈2013-02-02
一個(gè)javascript參數(shù)的小問(wèn)題
2008-03-03
前端判斷頁(yè)面是在PC端還是移動(dòng)端打開(kāi)四種方法
本文介紹幾種在前端開(kāi)發(fā)中用于判斷用戶(hù)設(shè)備類(lèi)型(PC端或移動(dòng)端)的方法,包括使用navigator.userAgent、媒體查詢(xún)、第三方庫(kù)detect.js和Vue框架插件vue-device-detect,這些方法有助于在開(kāi)發(fā)中處理設(shè)備適配和頁(yè)面權(quán)限問(wèn)題,需要的朋友可以參考下2024-10-10
OpenLayers實(shí)現(xiàn)點(diǎn)要素圖層的聚合顯示的方法
在很多情況下,點(diǎn)要素圖層中的要素?cái)?shù)量可能會(huì)成百上千,如果一個(gè)點(diǎn)要素圖層中的點(diǎn)數(shù)量很多,我們就會(huì)采取圖層聚合的方式對(duì)其進(jìn)行處理,本文就來(lái)介紹一下,感興趣的可以了解一下2021-09-09

