欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

參考EventEmitter實現(xiàn)完整訂閱發(fā)布功能函數(shù)

 更新時間:2023年02月12日 15:16:02   作者:拾光者  
這篇文章主要為大家介紹了參考EventEmitter實現(xiàn)完整訂閱發(fā)布功能函數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

前一篇文章 《實現(xiàn)一個簡單的訂閱發(fā)布功能函數(shù)|參考 EventEmitter》 實現(xiàn)了簡單版本的,本篇文章用 JS 完整實現(xiàn) Node.js 中的 EventEmitter

實現(xiàn)

EventEmitter 中有一些重復(fù)功能的函數(shù),或者已經(jīng)移除的函數(shù),這里不會進行實現(xiàn)。

主要會新增以下功能:

  • 新增默認(rèn)最大訂閱限制,且可進行更改
  • 可獲取所有的訂閱事件名稱
  • 可根據(jù)事件名獲取所有的監(jiān)聽函數(shù)
  • 默認(rèn)是往訂閱事件隊列尾部新增,現(xiàn)在新增 可往隊列頭部添加訂閱事件 的功能

根據(jù) 簡單版實現(xiàn) 為基礎(chǔ),再根據(jù)功能來新增一些屬性和方法。

需要新增內(nèi)部屬性:

  • maxListeners,默認(rèn)最多給特定事件添加了 10 個的訂閱,如果超過了則不會生效,且會有警告提示,如果需要更多,則需要調(diào)用 setMaxListeners 進行設(shè)置。
  • addListener,抽離新增訂閱的實現(xiàn),用于復(fù)用

需要新增功能函數(shù):

  • listeners 獲取
  • rawListeners 獲取所有訂閱的原始監(jiān)聽函數(shù)
  • listenerCount 獲取所有訂閱數(shù)量
  • eventNames 獲取所有訂閱事件名
  • prependListener 從頭部新增訂閱,如果代碼中需要先執(zhí)行的訂閱,才需要用到
  • prependOnceListener 從頭部新增一次性訂閱,如果代碼中需要先執(zhí)行的訂閱,才需要用到
  • setMaxListeners 設(shè)置最大訂閱數(shù)量
  • getMaxListeners 獲取最大訂閱數(shù)量

完整代碼實現(xiàn):

type Listener = (...args: any[]) => void;
type EventInfo = {
  // 監(jiān)聽器
  listener: Listener;
  // 備份,需要改變 listener 時,則需要備份,比如 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[]> = {};
  // 默認(rèn)最多給特定事件添加了 10 個的監(jiān)聽器
  private maxListeners = 10;
  // 訂閱實現(xiàn)
  private addListener = (eventName: string | symbol, listener: Listener, addToHead = false) => {
    if (!this.eventMap[eventName]) {
      this.eventMap[eventName] = [];
    }
    // 不能添加超過 maxListeners 的監(jiān)聽邏輯處理
    if (this.eventMap[eventName].length >= this.maxListeners) {
      console.warn(
        `maxListeners: ${this.maxListeners}, ${eventName.toString()} event has add ${this.maxListeners} listener,`
      );
    } else {
      if (addToHead) {
        this.eventMap[eventName].unshift({ listener });
      } else {
        this.eventMap[eventName].push({ listener });
      }
    }
    return this;
  };
  // 訂閱
  on = (eventName: string | symbol, listener: Listener) => {
    return this.addListener(eventName, listener);
  };
  // 取消訂閱
  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;
  };
  // 獲取所有訂閱的原始監(jiān)聽器
  listeners = (eventName: string | symbol) => {
    return this.eventMap[eventName]?.map((item) => item.bak || item.listener) || [];
  };
  // 返回名為 eventName 的事件的監(jiān)聽器數(shù)組的副本,包括任何封裝器(例如由 .once() 創(chuàng)建的封裝器)。
  rawListeners = (eventName: string | symbol) => {
    return this.eventMap[eventName]?.map((item) => item.listener) || [];
  };
  // 獲取所有訂閱數(shù)量
  listenerCount = (eventName: string | symbol) => {
    return this.eventMap[eventName]?.length || 0;
  };
  // 獲取所有 eventName
  eventNames = () => {
    const eventNames = [];
    for (const key in this.eventMap) {
      eventNames.push(key);
    }
    return eventNames;
  };
  // 將 listener 函數(shù)添加到名為 eventName 的事件的監(jiān)聽器數(shù)組的開頭。不檢查是否已添加 listener。 多次調(diào)用傳入相同的 eventName 和 listener 組合將導(dǎo)致多次添加和調(diào)用 listener。
  prependListener = (eventName: string | symbol, listener: Listener) => {
    return this.addListener(eventName, listener, true);
  };
  // 將名為 eventName 的事件的單次 listener 函數(shù)添加到監(jiān)聽器數(shù)組的開頭。 下次觸發(fā) eventName 時,將移除此監(jiān)聽器,然后再調(diào)用。
  prependOnceListener = (eventName: string | symbol, listener: Listener) => {
    const onceListener = createOnceListener(this, eventName, listener);
    this.prependListener(eventName, onceListener);
    return this;
  };
  // 當(dāng)前最大監(jiān)聽器數(shù)的值。 該值可以設(shè)置為 Infinity(或 0)以指示無限數(shù)量的監(jiān)聽器。
  setMaxListeners = (n: number) => {
    this.maxListeners = n;
    return this;
  };
  // 返回當(dāng)前最大監(jiān)聽器數(shù)的值,該值由 setMaxListeners(n) 設(shè)置或為默認(rèn)值 10。
  getMaxListeners = () => {
    return this.maxListeners;
  };
}
export const pubSub = new PubSub();

說明:

  • on 、onceprependListener 、prependOnceListener 幾個新增 listener 的函數(shù)都不檢查是否已添加 listener,多次調(diào)用傳入相同的 eventNamelistener 組合將導(dǎo)致多次添加和調(diào)用listener ,因此需要注意不要多次注入。

總結(jié)

如果你的應(yīng)用非常大,需要非常精細的管理事件,那么可以使用完整版實現(xiàn),如果不是的話,可以使用簡單版本。

以上就是參考EventEmitter實現(xiàn)完整訂閱發(fā)布功能函數(shù)的詳細內(nèi)容,更多關(guān)于EventEmitter訂閱發(fā)布功能函數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • node+express框架中連接使用mysql(經(jīng)驗總結(jié))

    node+express框架中連接使用mysql(經(jīng)驗總結(jié))

    這篇文章主要介紹了node+express框架中連接使用mysql(經(jīng)驗總結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • Node.js入門教程:在windows和Linux上安裝配置Node.js圖文教程

    Node.js入門教程:在windows和Linux上安裝配置Node.js圖文教程

    這篇文章主要介紹了Node.js入門教程:在windows和Linux上安裝配置Node.js的方法,本文圖文并茂,步驟明細,是學(xué)習(xí)安裝node.js的絕佳教程,需要的朋友可以參考下
    2014-08-08
  • NodeJS中的MongoDB快速入門詳細教程

    NodeJS中的MongoDB快速入門詳細教程

    MongoDB 是一個基于分布式文件存儲的數(shù)據(jù)庫,由 C++ 語言編寫。這篇文章主要介紹了NodeJS中的MongoDB快速入門詳細教程的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • 基于node.js之調(diào)試器詳解

    基于node.js之調(diào)試器詳解

    下面小編就為大家?guī)硪黄趎ode.js之調(diào)試器詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • nodejs中安裝ghost出錯的原因及解決方法

    nodejs中安裝ghost出錯的原因及解決方法

    本篇文章主要介紹了nodejs中安裝ghost出錯的原因及解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Node.js實現(xiàn)大文件斷點續(xù)傳示例詳解

    Node.js實現(xiàn)大文件斷點續(xù)傳示例詳解

    這篇文章主要為大家介紹了Node.js實現(xiàn)大文件斷點續(xù)傳示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • Node.js卸載與重裝及zip與msi安裝詳解

    Node.js卸載與重裝及zip與msi安裝詳解

    Node.js是一個JavaScript運行環(huán)境,可以使JavaScript這類腳本語言編寫出來的代碼運行速度獲得極大提升,下面這篇文章主要給大家介紹了關(guān)于Node.js卸載與重裝及zip與msi安裝的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • windows系統(tǒng)下更新nodejs版本的方案

    windows系統(tǒng)下更新nodejs版本的方案

    這篇文章主要介紹了windows系統(tǒng)下更新nodejs版本的方案,在文章給大家介紹了NodeJS 與 npm 在Windows下升級問題,需要的朋友可以參考下
    2017-11-11
  • Node.js 實現(xiàn)搶票小工具 & 短信通知提醒功能

    Node.js 實現(xiàn)搶票小工具 & 短信通知提醒功能

    這篇文章主要介紹了Node.js 實現(xiàn)搶票小工具 & 短信通知提醒功能,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-10-10
  • Node.js 中如何收集和解析命令行參數(shù)

    Node.js 中如何收集和解析命令行參數(shù)

    這篇文章主要介紹了Node.js 中如何收集和解析命令行參數(shù),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論