ionic4-EventBus(事件总线)

环境

node 10.15.0
ionic 4.12.0
cordova 9.0
# platforms
cordova-android:8.0.0
cordova-ios: 5.0.0

前言:
AngularJs 中,我们可以使用on来发出、监听广播,实现全局的消息/事件通信;在Angular2+版本,取消了广播功能。
下面我们将使用RxJS的特性来实现事件总线。
注:代码源自ng-event-bus

用法

第一步

导入

# app.module.ts
providers: [
  NgEventBus
]

注入

# some component
constructor(private eventBus: NgEventBus){...}

第二步

发送事件

this.eventBus.cast('test:start', {data: 'hahaha'});

第三步

接收事件

# 接收单个
this.eventBus.on('test:start').subscribe((message) => {
  console.log(message);
});
# 接收test下所有
this.eventBus.on('test:**').subscribe((message) => {
  console.log(message);
});

源码分析

事件定义

interface EventBusMessage {
  key: string;
  data?: any;
}

this._eventBus 用于收发事件。
此处为何使用Subject?

什么是Subject(主题)?RxJS Subject是一种特殊类型的Observable,允许将值多播到多个观察者Observer。虽然普通的Observable是单播的(每个订阅的Observer都拥有Observable的独立执行),但Subject是多播的。

每个Subject都是一个Observer。它是一个含有next(v),error(e)和complete()的对象。要向Subject提供新值,只需调用next(theValue),它将被多播到已注册接受该Subject的观察者。

constructor() {
  this._eventBus = new Subject();
}

发送事件

如Subject的定义,只需调用next方法,就可已广播到所有订阅此Subject的观察者。

public send(key: string, data?: any): void {
  if (typeof key !== 'string' || !key.length) {
    throw Error('key must be a string and mustn\'t be empty.');
  }
  this._eventBus.next({key, data});
}

接收事件

参数:事件key
filter:过滤key
此处涉及到key匹配,下面单独说明

public on(key: string): Observable {
  return this._eventBus.asObservable().pipe(
    filter((event: EventBusMessage): event is EventBusMessage => this.keyMatch(event.key, key)),
    map(event => event.data)
  );
}

key匹配
具体分析将以注释的形式展现

public keyMatch(key: string, wildcard: string): boolean {
    const w = '*';
    const ww = '**';
    
    const partMatch = (wl, k) => {
      return (wl === w) || (wl === k);
    };
    const sep = this.separator;
    // 以*分割key etc: [app, start]
    const kArr = key.split(sep);
    // 监听key分割 etc: [app,**]
    const wArr = wildcard.split(sep);
    const kLen = kArr.length;
    const wLen = wArr.length;
    const max = Math.max(kLen, wLen);
    for (let i = 0; i < max; i++) {
      const cK = kArr[i];
      const cW = wArr[i];
      // 若:后匹配上** && :前不为undefined 则匹配上
      if (cW === ww && (typeof cK !== 'undefined')) {
        return true;
      }
      // :前后匹配, 2部分均不同 匹配失败
      if (!partMatch(cW, cK)) {
        return false;
      }
    }
    return true;
  }

下一篇将介绍RxJS的订阅管理。

你可能感兴趣的:(ionic4-EventBus(事件总线))