自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

PixiJS 源碼解讀:Runner 事件通知類

開發(fā) 前端
首先通過(guò) New Runner(name) 創(chuàng)建一個(gè) Runner 實(shí)例,這里需要傳入一個(gè)字符串類型的 name。之后通過(guò) Runner.add 方法添加一個(gè)監(jiān)聽器對(duì)象 listener。最后通過(guò) Runner.emit 方法觸發(fā)事件,之前綁定的監(jiān)聽器的 listener[name] 方法會(huì)被執(zhí)行。

大家好,我是前端西瓜哥。

PixiJS 的 Runner 類是高性能的事件通知類。其實(shí)就是一個(gè)簡(jiǎn)易的發(fā)布訂閱庫(kù)。

發(fā)布訂閱庫(kù),我們比較熟悉的就是 Nodejs 的 EventEmitter。

不過(guò)這個(gè) Runner 的邏輯稍微有點(diǎn)特殊,后面會(huì)說(shuō)它怎么特殊。

使用示例

import { Runner } from "@pixi/runner";

const loadedRunner = new Runner("loaded");

const listener = {
  loaded(n1: number, n2: number) {
    console.log("前端西瓜哥", n1, n2);
  }
};

loadedRunner.add(listener);

loadedRunner.emit(1, 2); // 輸出:前端西瓜哥 1 2

首先通過(guò) new Runner(name) 創(chuàng)建一個(gè) Runner 實(shí)例,這里需要傳入一個(gè)字符串類型的 name。

之后通過(guò) runner.add 方法添加一個(gè)監(jiān)聽器對(duì)象 listener。

最后通過(guò) runner.emit 方法觸發(fā)事件,之前綁定的監(jiān)聽器的 listener[name]  方法會(huì)被執(zhí)行。

和我們熟悉的 Nodejs 的 EventEmitter 不一樣,有一些特別的點(diǎn):

  • 一個(gè) Runner 只能綁定一個(gè)事件,不像 EventEmitter 的 on 方法,還能多指定一個(gè)事件名。
  • 綁定的監(jiān)聽器是一個(gè)對(duì)象,并會(huì)在觸發(fā)事件時(shí)調(diào)用 Runner 初始化時(shí)設(shè)置的 name 對(duì)應(yīng)的函數(shù)。這樣做的優(yōu)點(diǎn)是監(jiān)聽器執(zhí)行時(shí) this 不會(huì)丟失。EventEmitter 綁定的直接就是一個(gè)函數(shù)。

然后它和 EventEmitter 一樣,是類型不安全的:emit 傳的參數(shù)并沒有限定。

源碼解讀

構(gòu)造函數(shù)

首先是構(gòu)造函數(shù)。

export class Runner {
  public items: any[];
  private _name: string;
  private _aliasCount: number;

  constructor(name: string) {
    this.items = [];
    this._name = name;
    this._aliasCount = 0;
  }

  // ...
}

簡(jiǎn)單的初始化操作,這個(gè) name 我們要保存下來(lái),之后我們執(zhí)行監(jiān)聽器對(duì)象,需要這個(gè) name 作為 key 去找到方法去執(zhí)行。

items 是保存監(jiān)聽器對(duì)象的數(shù)組。

_aliasCount 是一個(gè)標(biāo)識(shí),標(biāo)識(shí)是否在 emit(觸發(fā)事件)階段,用于防止 emit 時(shí)改變了 items,導(dǎo)致不可預(yù)期的行為。

添加監(jiān)聽器

然后是 add 方法,用于添加監(jiān)聽器。

public add(item: unknown): this {
  if ((item as any)[this._name]) {
    this.ensureNonAliasedItems();
    this.remove(item); // 如果存在,先刪除
    this.items.push(item); // 添加的末尾
  }

  return this;
}

監(jiān)聽器對(duì)象必須有對(duì)應(yīng)的 key 才能被添加進(jìn)去。

為了保證 this.items 不出現(xiàn)多個(gè)相同的對(duì)象,會(huì)將其刪除。然后把監(jiān)聽器對(duì)象放到 this.items 末尾。

返回 this,是為了實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用。

this.ensureNonAliasedItems() 方法用于處理一些特殊 case。

比如在 emit 階段發(fā)生了 add 操作,PixiJS 會(huì)防止其在本輪 emit 被執(zhí)行,為此會(huì)拷貝一份新的 items。

private ensureNonAliasedItems(): void {
  if (this._aliasCount > 0 && this.items.length > 1) {
    this._aliasCount = 0;
    this.items = this.items.slice(0);
  }
}

事件觸發(fā)

emit 會(huì)觸發(fā)事件,別名有 dispatch、run。

public emit(
  a0?: unknown,
  a1?: unknown,
  a2?: unknown,
  a3?: unknown,
  a4?: unknown,
  a5?: unknown,
  a6?: unknown,
  a7?: unknown
): this {
  if (arguments.length > 8) {
    throw new Error('max arguments reached');
  }

  const { name, items } = this;
  this._aliasCount++;

  for (let i = 0, len = items.length; i < len; i++) {
    items[i][name](a0, a1, a2, a3, a4, a5, a6, a7);
  }

  if (items === this.items) {
    this._aliasCount--;
  }
  return this;
}

核心邏輯:遍歷 this.items 數(shù)組,順序執(zhí)行監(jiān)聽器的 key 為 this.name 的方法。

刪除監(jiān)聽器

remove,刪除監(jiān)聽器。

public remove(item: unknown): this {
  const index = this.items.indexOf(item);

  if (index !== -1) {
    this.ensureNonAliasedItems();
    this.items.splice(index, 1);
  }

  return this;
}

其他方法

contains:查看指定對(duì)象是已經(jīng)是被綁定為監(jiān)聽器。

public contains(item: unknown): boolean {
  return this.items.includes(item);
}

removeAll:刪除所有監(jiān)聽器.

public removeAll(): this {
  this.ensureNonAliasedItems();
  this.items.length = 0;
  return this;
}

destory:銷毀。銷毀后就不能再用了,否則會(huì)報(bào)錯(cuò)。

public destroy(): void {
  this.removeAll();
  this.items = null;
  this._name = null;
}

empty,是一個(gè) getter,判斷是否存在監(jiān)聽器集合。PixiJS 確實(shí)喜歡用 getter

public get empty(): boolean {
  return this.items.length === 0;
}

結(jié)尾

通常我們會(huì)在 PixiJS 的類中看到名為 disposeRunner 的成員屬性,說(shuō)明這個(gè)類會(huì)通過(guò)事件訂閱的方式和其他模塊通信。

發(fā)布訂閱庫(kù)我實(shí)在是分析得夠多了,基本的套路就 3 個(gè):把監(jiān)聽器函數(shù)放到有序表中,觸發(fā)事件時(shí)順序調(diào)用,支持刪除監(jiān)聽器(3 種風(fēng)格)。

PixiJS 的 Runner 功能并不多,其中特殊的調(diào)用邏輯(調(diào)用監(jiān)聽器的特定 key)顯然是用于 PixiJS 內(nèi)部模塊的風(fēng)格。

責(zé)任編輯:姜華 來(lái)源: 前端西瓜哥
相關(guān)推薦

2023-06-07 08:13:46

PixiJSCanvas 庫(kù)

2023-10-09 07:49:33

PixiJSWebGL

2023-06-08 08:16:33

TickerPixiJS

2024-09-06 09:37:45

WebApp類加載器Web 應(yīng)用

2011-05-06 15:00:52

Service BroSQL Server

2015-06-15 10:32:44

Java核心源碼解讀

2024-10-28 08:15:32

2010-01-27 10:37:17

Android圖片瀏覽

2016-08-29 19:12:52

JavascriptBackbone前端

2010-02-23 14:48:38

WCF事件通知

2015-03-31 14:15:12

JavaJava事件通知

2010-01-04 14:06:35

Silverlight

2010-01-26 13:55:57

Android分享功能

2010-01-28 15:54:19

Android單元測(cè)試

2009-12-21 18:10:50

WCF實(shí)現(xiàn)事件通知

2021-03-19 08:00:00

網(wǎng)絡(luò)安全漏洞數(shù)據(jù)安全

2010-01-04 17:03:27

Silverlight

2021-02-05 09:00:00

開發(fā)IT事件管理

2022-07-19 13:51:47

數(shù)據(jù)庫(kù)Hikari連接池

2009-12-07 15:34:18

PHP類的封裝
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)