最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

參考EventEmitter實現完整訂閱發(fā)布功能函數

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

引言

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

實現

EventEmitter 中有一些重復功能的函數,或者已經移除的函數,這里不會進行實現。

主要會新增以下功能:

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

根據 簡單版實現 為基礎,再根據功能來新增一些屬性和方法。

需要新增內部屬性:

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

需要新增功能函數:

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

完整代碼實現:

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[]> = {};
  // 默認最多給特定事件添加了 10 個的監(jiān)聽器
  private maxListeners = 10;
  // 訂閱實現
  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 函數
  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)聽器數組的副本,包括任何封裝器(例如由 .once() 創(chuàng)建的封裝器)。
  rawListeners = (eventName: string | symbol) => {
    return this.eventMap[eventName]?.map((item) => item.listener) || [];
  };
  // 獲取所有訂閱數量
  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 函數添加到名為 eventName 的事件的監(jiān)聽器數組的開頭。不檢查是否已添加 listener。 多次調用傳入相同的 eventName 和 listener 組合將導致多次添加和調用 listener。
  prependListener = (eventName: string | symbol, listener: Listener) => {
    return this.addListener(eventName, listener, true);
  };
  // 將名為 eventName 的事件的單次 listener 函數添加到監(jiān)聽器數組的開頭。 下次觸發(fā) eventName 時,將移除此監(jiān)聽器,然后再調用。
  prependOnceListener = (eventName: string | symbol, listener: Listener) => {
    const onceListener = createOnceListener(this, eventName, listener);
    this.prependListener(eventName, onceListener);
    return this;
  };
  // 當前最大監(jiān)聽器數的值。 該值可以設置為 Infinity(或 0)以指示無限數量的監(jiān)聽器。
  setMaxListeners = (n: number) => {
    this.maxListeners = n;
    return this;
  };
  // 返回當前最大監(jiān)聽器數的值,該值由 setMaxListeners(n) 設置或為默認值 10。
  getMaxListeners = () => {
    return this.maxListeners;
  };
}
export const pubSub = new PubSub();

說明:

  • on 、once 、prependListenerprependOnceListener 幾個新增 listener 的函數都不檢查是否已添加 listener,多次調用傳入相同的 eventNamelistener 組合將導致多次添加和調用listener ,因此需要注意不要多次注入。

總結

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

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

相關文章

  • 一次NodeJS內存泄漏排查的實戰(zhàn)記錄

    一次NodeJS內存泄漏排查的實戰(zhàn)記錄

    這篇文章主要給大家介紹了一次NodeJS內存泄漏排查的實戰(zhàn)記錄,文中給出了詳細的排查過程以及內存泄漏的解決方法,大家可以學習一下以備不時之需,需要的朋友可以參考下
    2022-03-03
  • nodejs下載指定版本完整圖文步驟

    nodejs下載指定版本完整圖文步驟

    node.js官方版是一款專業(yè)性非常強的瀏覽輔助工具軟件,這款軟件操作十分的簡單、功能也是非常的強勁,下面這篇文章主要給大家介紹了關于nodejs下載指定版本的相關資料,需要的朋友可以參考下
    2023-12-12
  • node.js 發(fā)布訂閱模式的實例

    node.js 發(fā)布訂閱模式的實例

    下面小編就為大家?guī)硪黄猲ode.js 發(fā)布訂閱模式的實例。小編覺得挺不錯的,現在就想給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • Mac OS X 系統下安裝和部署Egret引擎開發(fā)環(huán)境

    Mac OS X 系統下安裝和部署Egret引擎開發(fā)環(huán)境

    之前的文章,我們已經介紹了Windows 系統下安裝和部署Egret的開發(fā)環(huán)境,那么,這篇文檔中,我們主要介紹在Mac環(huán)境中安裝Egret以及部署
    2014-09-09
  • nodejs個人博客開發(fā)第三步 載入頁面

    nodejs個人博客開發(fā)第三步 載入頁面

    這篇文章主要為大家詳細介紹了nodejs個人博客開發(fā)的載入頁面,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Node.js+ES6+dropload.js實現移動端下拉加載實例

    Node.js+ES6+dropload.js實現移動端下拉加載實例

    這個demo服務由Node搭建服務、下拉加載使用插件dropload,數據渲染應用了ES6中的模板字符串。有興趣的小伙伴可以自己嘗試下
    2017-06-06
  • Node.js+Express.js+TS實現簡單圖床腳本

    Node.js+Express.js+TS實現簡單圖床腳本

    在這篇博客文章中,我將介紹如何使用 TypeScript 和 Express 框架來編寫一個簡單的圖床腳本,可以將本地圖片上傳到服務器,并返回圖片的 URL,這樣,你就可以在 Markdown 文檔中方便地引用圖片,而不用擔心圖片的存儲和管理問題
    2023-10-10
  • Nodejs異步回調的優(yōu)雅處理方法

    Nodejs異步回調的優(yōu)雅處理方法

    這篇文章主要介紹了Nodejs異步回調的優(yōu)雅處理方法,本文使用了ES6中的新特性,用一種十分優(yōu)雅的方式解決了回調問題,需要的朋友可以參考下
    2014-09-09
  • 詳解如何優(yōu)雅在webpack項目實現mock服務器

    詳解如何優(yōu)雅在webpack項目實現mock服務器

    這篇文章主要為大家介紹了詳解如何優(yōu)雅在webpack項目實現mock服務器,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • nodejs制作爬蟲實現批量下載圖片

    nodejs制作爬蟲實現批量下載圖片

    本文給大家分享的是作者使用nodejs制作爬蟲來爬去圖片并批量下載的全過程,非常的細致,有需要的小伙伴可以參考下
    2017-05-05

最新評論

太康县| 兰溪市| 隆回县| 巴塘县| 溆浦县| 忻城县| 灯塔市| 泾源县| 富平县| 凤凰县| 灵丘县| 徐闻县| 松溪县| 双鸭山市| 色达县| 大埔区| 陆良县| 衡山县| 萝北县| 电白县| 平安县| 尼玛县| 花莲县| 扎囊县| 雷波县| 通州区| 隆林| 芦溪县| 河津市| 沁源县| 什邡市| 阜新市| 弋阳县| 神池县| 来凤县| 昌宁县| 海盐县| 克什克腾旗| 满洲里市| 云南省| 汤原县|