2019年02月16日 21:11
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

又让你痛不欲生,又让你趁醉装疯,终有天脱胎换骨,直到哭着笑才懂。欲问青天这人生有几何,有几何啊?

QQ截图20190216201743.png

今年去城墙下转了一圈,想到这几年的工作,这几年的经历,我到底是图什么。也许你勇敢的跨出一步,就是这一步。发感慨也没啥用,实际行动才可以。

今天主要是看一下类似于观察者模式的广播通知,首先我们需要安装rxjs包。安装好之后,引入我们的项目。

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';

@Injectable()
export class BroadCaster {
  private subject: Subject<BroadCastEvent>;

  constructor() {
    this.subject = new Subject<BroadCastEvent>();
  }

  broadcast(key: any, data?: any) {
    this.subject.next({ key, data });
  }

  on<T>(key: any, data?: any) {
    return this.subject.asObservable()
      .pipe(
        filter(e => e.key === key),
        map(e => <T>e.data))
      ;
  }
}

interface BroadCastEvent {
  key: any;
  data?: any
}

首先我们定义好接口BroadCastEvent,包含两个属性。然后再定义通知类,通知类必须是可注入的,因此需要标记@Injectable。

在构造函数中先实例化Subject泛型类,注意这里的泛型类型就是我们定义的接口类型。

在这里主要有两个方法,broadcast,包含key和data参数。收到后调用subject的next方法,将消息传递给接收者。

然后我们还有个on方法,当别的模块发消息出来的收,我们会收到消息。这里我们有个pipe方法,第一个参数是过滤用的,举个例子。

还是洗浴中心,突击检查。此时前台只希望将消息通知到三楼洗浴场,四楼宾馆。此时就需要判断通知是不是给三四楼发的,就需要通过这个key来判断。如果是发给三四楼的,就会拿出消息通知给三四楼。所以这里还有个map方法,拿到通知的数据。

接下来我们看看它的应用,我把这个类改一下,让他通俗易懂。

import { Injectable } from '@angular/core';
import { Observable ,  Subject } from 'rxjs';

@Injectable()
export class MessageService {
    private subject = new Subject<any>();

    sendMessage(message: { type: string, data: any }) {
        this.subject.next({ text: message });
    }

    clearMessage() {
        this.subject.next();
    }

    getMessage(): Observable<{ type: string, data: any }> {
        return this.subject.asObservable();
    }
}

一目了然,一个sendMessage,一个getMessage。

在页面应用,我们需要引入Subscription类。这个类可以实现消息订阅,取消订阅,对于我们来说刚好订阅广播出的消息。由于涉及真实项目,只贴出部分代码。

import { Subscription } from 'rxjs';

@Component({
    selector: 'website-category',
    templateUrl: 'websitecategory.component.html'
})
export class WebsiteCategoryComponent implements AfterViewInit, OnDestroy {
    constructor(
        private messageService: MessageService) {
        this.subscription = this.messageService.getMessage()
            .subscribe((message: any) => {
                if (message.text.type == 'ItemBaseInfoRefresh') {
                    this.initWebsiteCategory(message.text.data);
                }
            });
    }
    
    subscription: Subscription;

上面的是接收的页面,首先会判断发送的消息是不是给自己的,如果是自己的就做自己的事情。

其实另一个发送页面只是负责发送消息。

this.messageService.sendMessage({ type: 'ItemBaseInfoRefresh', data: null });

那么其实大家就想问怎么接收到的消息。其实这里两个组件构造函数中注入的messageService是一个对象。因此接收页面去subscrible订阅的还是messageService的消息。ok,其实实现就是这么简单。

最后我不得不说一下我对subject的理解,这个东西是一种可以允许多订阅的Observable,对于每一个订阅者,Subject都会将其维护在自己的Observer列表中。因此在我们的项目中,有好几个页面都是订阅这个subject。那么如果Component卸载后订阅怎么清除呢,很简单,看下面。

ngOnDestroy() {
    this.subscription.unsubscribe();
}

OK,关于通知就说这么多,就是利用Subject的多路订阅通知实现观察者模式。

网上也有比较详细的解释:https://segmentfault.com/a/1190000005069851

发表评论
匿名  
用户评论
暂无评论