当前位置:首页 > 科技  > 软件

PixiJS 源码解读:Runner 事件通知类

来源: 责编: 时间:2023-10-13 14:34:39 176观看
导读大家好,我是前端西瓜哥。PixiJS 的 Runner 类是高性能的事件通知类。其实就是一个简易的发布订阅库。发布订阅库,我们比较熟悉的就是 Nodejs 的 EventEmitter。不过这个 Runner 的逻辑稍微有点特殊,后面会说它怎么特殊。

wm128资讯网——每日最新资讯28at.com

大家好,我是前端西瓜哥。wm128资讯网——每日最新资讯28at.com

PixiJS 的 Runner 类是高性能的事件通知类。其实就是一个简易的发布订阅库。wm128资讯网——每日最新资讯28at.com

发布订阅库,我们比较熟悉的就是 Nodejs 的 EventEmitter。wm128资讯网——每日最新资讯28at.com

不过这个 Runner 的逻辑稍微有点特殊,后面会说它怎么特殊。wm128资讯网——每日最新资讯28at.com

使用示例

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

首先通过 new Runner(name) 创建一个 Runner 实例,这里需要传入一个字符串类型的 name。wm128资讯网——每日最新资讯28at.com

之后通过 runner.add 方法添加一个监听器对象 listener。wm128资讯网——每日最新资讯28at.com

最后通过 runner.emit 方法触发事件,之前绑定的监听器的 listener[name]  方法会被执行。wm128资讯网——每日最新资讯28at.com

和我们熟悉的 Nodejs 的 EventEmitter 不一样,有一些特别的点:wm128资讯网——每日最新资讯28at.com

  • 一个 Runner 只能绑定一个事件,不像 EventEmitter 的 on 方法,还能多指定一个事件名。
  • 绑定的监听器是一个对象,并会在触发事件时调用 Runner 初始化时设置的 name 对应的函数。这样做的优点是监听器执行时 this 不会丢失。EventEmitter 绑定的直接就是一个函数。

然后它和 EventEmitter 一样,是类型不安全的:emit 传的参数并没有限定。wm128资讯网——每日最新资讯28at.com

源码解读

构造函数

首先是构造函数。wm128资讯网——每日最新资讯28at.com

export class Runner {  public items: any[];  private _name: string;  private _aliasCount: number;  constructor(name: string) {    this.items = [];    this._name = name;    this._aliasCount = 0;  }  // ...}

简单的初始化操作,这个 name 我们要保存下来,之后我们执行监听器对象,需要这个 name 作为 key 去找到方法去执行。wm128资讯网——每日最新资讯28at.com

items 是保存监听器对象的数组。wm128资讯网——每日最新资讯28at.com

_aliasCount 是一个标识,标识是否在 emit(触发事件)阶段,用于防止 emit 时改变了 items,导致不可预期的行为。wm128资讯网——每日最新资讯28at.com

添加监听器

然后是 add 方法,用于添加监听器。wm128资讯网——每日最新资讯28at.com

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

监听器对象必须有对应的 key 才能被添加进去。wm128资讯网——每日最新资讯28at.com

为了保证 this.items 不出现多个相同的对象,会将其删除。然后把监听器对象放到 this.items 末尾。wm128资讯网——每日最新资讯28at.com

返回 this,是为了实现链式调用。wm128资讯网——每日最新资讯28at.com

this.ensureNonAliasedItems() 方法用于处理一些特殊 case。wm128资讯网——每日最新资讯28at.com

比如在 emit 阶段发生了 add 操作,PixiJS 会防止其在本轮 emit 被执行,为此会拷贝一份新的 items。wm128资讯网——每日最新资讯28at.com

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

事件触发

emit 会触发事件,别名有 dispatch、run。wm128资讯网——每日最新资讯28at.com

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 数组,顺序执行监听器的 key 为 this.name 的方法。wm128资讯网——每日最新资讯28at.com

删除监听器

remove,删除监听器。wm128资讯网——每日最新资讯28at.com

public remove(item: unknown): this {  const index = this.items.indexOf(item);  if (index !== -1) {    this.ensureNonAliasedItems();    this.items.splice(index, 1);  }  return this;}

其他方法

contains:查看指定对象是已经是被绑定为监听器。wm128资讯网——每日最新资讯28at.com

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

removeAll:删除所有监听器.wm128资讯网——每日最新资讯28at.com

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

destory:销毁。销毁后就不能再用了,否则会报错。wm128资讯网——每日最新资讯28at.com

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

empty,是一个 getter,判断是否存在监听器集合。PixiJS 确实喜欢用 getterwm128资讯网——每日最新资讯28at.com

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

结尾

通常我们会在 PixiJS 的类中看到名为 disposeRunner 的成员属性,说明这个类会通过事件订阅的方式和其他模块通信。wm128资讯网——每日最新资讯28at.com

发布订阅库我实在是分析得够多了,基本的套路就 3 个:把监听器函数放到有序表中,触发事件时顺序调用,支持删除监听器(3 种风格)。wm128资讯网——每日最新资讯28at.com

PixiJS 的 Runner 功能并不多,其中特殊的调用逻辑(调用监听器的特定 key)显然是用于 PixiJS 内部模块的风格。wm128资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-13254-0.htmlPixiJS 源码解读:Runner 事件通知类

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 如何更优雅的编程?面向接口编程四大法宝!

下一篇: 深入了解桶排序:原理、性能分析与 Java 实现

标签:
  • 热门焦点
  • 6月iOS设备好评榜:第一蝉联榜首近一年

    6月iOS设备好评榜:第一蝉联榜首近一年

    作为安兔兔各种榜单里变化最小的那个,2023年6月的iOS好评榜和上个月相比没有任何排名上的变化,仅仅是部分设备好评率的下降,长年累月的用户评价和逐渐退出市场的老款机器让这
  • 8月总票房已突破10亿!《封神》第一:口碑已经成了

    8月总票房已突破10亿!《封神》第一:口碑已经成了

    8月5日消息,据灯塔专业版数据,截至8月5日9时35分,8月总票房(含预售)已突破10亿。其中,《封神》以大比分的优势领先。根据官方消息,目前该片总票房已经超过14.
  • 线程通讯的三种方法!通俗易懂

    线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • 掘力计划第 20 期:Flutter 混合开发的混乱之治

    掘力计划第 20 期:Flutter 混合开发的混乱之治

    在掘力计划系列活动第20场,《Flutter 开发实战详解》作者,掘金优秀作者,Github GSY 系列目负责人恋猫的小郭分享了Flutter 混合开发的混乱之治。Flutter 基于自研的 Skia 引擎
  • 学习JavaScript的10个理由...

    学习JavaScript的10个理由...

    作者 | Simplilearn编译 | 王瑞平当你决心学习一门语言的时候,很难选择到底应该学习哪一门,常用的语言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 大厂卷向扁平化

    大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • 半导体需求下滑 三星电子DS业务部门今年营业亏损预计超10万亿韩元

    半导体需求下滑 三星电子DS业务部门今年营业亏损预计超10万亿韩元

    7月17日消息,据外媒报道,去年下半年开始的半导体需求下滑,影响到了三星电子、SK海力士、英特尔等诸多厂商,营收明显下滑,部分厂商甚至出现了亏损。作为
  • Android 14发布:首批适配机型公布

    Android 14发布:首批适配机型公布

    5月11日消息,谷歌在今天凌晨举行了I/O大会,本次发布会谷歌带来了自家的AI语言模型PaLM 2、谷歌Pixel Fold折叠屏、谷歌Pixel 7a手机,同时发布了Androi
  • OPPO K11评测:旗舰级IMX890加持 2000元档最强影像手机

    OPPO K11评测:旗舰级IMX890加持 2000元档最强影像手机

    【Techweb评测】中端机型用户群体巨大,占了中国目前手机市场的大头,一直以来都是各手机品牌的“必争之地”,其中OPPO K系列机型一直以来都以高品质、
Top
Baidu
map