參考?EventEmitter實(shí)現(xiàn)一個(gè)簡(jiǎn)單的訂閱發(fā)布功能函數(shù)
目的
訂閱發(fā)布模式 應(yīng)該是 JS 最常用的設(shè)計(jì)模式,也可稱之為 觀察者模式,前端各個(gè)方面都會(huì)涉及到它,比如:瀏覽器中的事件監(jiān)聽機(jī)制、nodejs 中的 EventEmitter 、redux 數(shù)據(jù)傳遞實(shí)現(xiàn)等等。
不管是 瀏覽器中的事件監(jiān)聽機(jī)制 還是 nodejs 中的 EventEmitter,都只能在各自的環(huán)境進(jìn)行運(yùn)行。因此我們需要用一份代碼來(lái)讓多端都可以調(diào)用,EventEmitter 功能更全面,我們借鑒它來(lái)實(shí)現(xiàn)一個(gè)完整的 PubSub。
實(shí)現(xiàn)
主要參考 EventEmitter 的功能來(lái),本篇文章提供 簡(jiǎn)單實(shí)現(xiàn),下一篇提供了 完整實(shí)現(xiàn),點(diǎn)擊即可去查看,代碼有問(wèn)題歡迎評(píng)論區(qū)指出。
實(shí)現(xiàn)常用功能:
on: 用于添加訂閱off: 用于取消訂閱once: 用于添加一次性訂閱emit: 用于發(fā)布事件,讓訂閱者收到通知
完整代碼實(shí)現(xiàn):
type Listener = (...args: any[]) => void;
type EventInfo = {
// 監(jiān)聽器
listener: Listener;
// 備份,需要改變 listener 時(shí),則需要備份,比如 once
bak?: Listener;
};
// 創(chuàng)建一次性監(jiān)聽器
function createOnceListener(pub: PubSub, eventName: string | symbol, listener: Listener) {
const onceListener = (...args: any[]) => {
// 執(zhí)行一次后直接取消訂閱
listener(...args);
pub.off(eventName, listener);
};
return onceListener;
}
export class PubSub {
private eventMap: Record<string | symbol, EventInfo[]> = {};
// 訂閱
on = (eventName: string | symbol, listener: Listener) => {
if (!this.eventMap[eventName]) {
this.eventMap[eventName] = [];
}
this.eventMap[eventName].push({ listener });
return this;
};
// 取消訂閱
off = (eventName: string | symbol, listener: Listener) => {
if (this.eventMap[eventName]) {
this.eventMap[eventName] = this.eventMap[eventName].filter((item) => {
// once listener 取消訂閱
if (item.bak) {
return item.bak !== listener;
}
// 正常 listener 取消訂閱
return item.listener !== listener;
});
}
return this;
};
// 類似 EventEmitter 中的 emit 函數(shù)
emit = (eventName: string | symbol, ...args: any[]) => {
this.eventMap[eventName]?.forEach((item) => {
item.listener(...args);
});
return this;
};
// 只訂閱一次
once = (eventName: string | symbol, listener: Listener) => {
const onceListener = createOnceListener(this, eventName, listener);
this.on(eventName, onceListener);
return this;
};
}
// 不需要有全局訂閱功能的,可以去掉這個(gè)
export const pubSub = new PubSub();
實(shí)現(xiàn)說(shuō)明:
- 不管訂閱還是發(fā)布的時(shí)候都需要判讀是否有已存在的隊(duì)列。
eventMap用于存儲(chǔ)訂閱相關(guān)信息。once使用createOnceListener函數(shù)實(shí)現(xiàn),給原listener添加一層包裹,執(zhí)行一次后自動(dòng)注銷。off注銷監(jiān)聽時(shí)需要考慮once的listener被添加了一層包裹,需要用備份的原始listener來(lái)判斷。listener函數(shù)需要考慮有多個(gè)參數(shù)。- 操作性的函數(shù)的返回值為
this,用于鏈?zhǔn)秸{(diào)用,比如pubSub.emit("test").off("test")
總結(jié)
實(shí)現(xiàn)過(guò)程是通過(guò)閱讀 EventEmitter 官方文檔的 API 來(lái)進(jìn)行反向?qū)崿F(xiàn)的,typescript 類型可以直接通過(guò) nodejs 使用的時(shí)候獲取,這也一般是想實(shí)現(xiàn)某一個(gè)功能的方法。
有不對(duì)的地方歡迎指出,感謝??。
點(diǎn)擊查看下一篇 完整實(shí)現(xiàn)。
以上就是參考 EventEmitter實(shí)現(xiàn)一個(gè)簡(jiǎn)單的訂閱發(fā)布功能函數(shù)的詳細(xì)內(nèi)容,更多關(guān)于EventEmitter訂閱發(fā)布功能函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
windows系統(tǒng)上完全卸載并重裝Node的步驟(親測(cè)可用)
對(duì)于Windows平臺(tái)來(lái)說(shuō),所有的應(yīng)用程序,其安裝卸載都是一樣的,node.js也不例外,但是還是很多用戶不明白,下面這篇文章主要給大家介紹了關(guān)于windows系統(tǒng)上完全卸載并重裝Node的步驟,需要的朋友可以參考下2023-03-03
從零學(xué)習(xí)node.js之簡(jiǎn)易的網(wǎng)絡(luò)爬蟲(四)
簡(jiǎn)單的爬蟲實(shí)現(xiàn)原理很簡(jiǎn)單:發(fā)送http請(qǐng)求至目標(biāo)地址獲取HTML頁(yè)面數(shù)據(jù),然后從獲取來(lái)的頁(yè)面數(shù)據(jù)中提取需要的數(shù)據(jù)保存。下面這篇文章主要介紹了利用node.js實(shí)現(xiàn)簡(jiǎn)易的網(wǎng)絡(luò)爬蟲的相關(guān)資料,需要的朋友可以參考下。2017-02-02
使用Express+Node.js對(duì)mysql進(jìn)行增改查操作?
這篇文章主要介紹了使用Express+Node.js對(duì)mysql進(jìn)行增改查操作,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
koa2實(shí)現(xiàn)登錄注冊(cè)功能的示例代碼
這篇文章主要介紹了koa2實(shí)現(xiàn)登錄注冊(cè)功能的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
Node.js v8.0.0正式發(fā)布!看看帶來(lái)了哪些主要新特性
Node.js v8.0.0 已正式發(fā)布。v8.0.0 是下一個(gè)主要的版本,帶來(lái)了一系列重大的變化和新功能,內(nèi)容十分多!下面這篇文章主要帶著大家一起看看Node.js v8.0.0帶來(lái)了哪些主要新特性,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-06-06
零基礎(chǔ)實(shí)現(xiàn)node+express個(gè)性化聊天室的示例
這篇文章主要介紹了零基礎(chǔ)實(shí)現(xiàn)node+express個(gè)性化聊天室的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02

