发布于 1年前

RxJs——subject理解

什么是subject

首先我们来理解什么是subject,按照官方的定义:

A Subject is a special type of Observable that allows values to be multicasted to many Observers.

Subjects are like EventEmitters.

从定义我们看出subject就是一种允许发送值到多个观察者的特殊类型的Observable。它很像事件发送器。

我们分解一下,在结合网络上的一些分析,看看从定义中可以看出啥?

网络定义

A Subject is both an <strong>Observable</strong> and an <strong>Observer</strong> that allows values to be multicasted to many Observers, unlike Observables, where each subscriber owns an independent execution of the Observable.

subject继承了Observable,同时它也是一个Observer,允许值被广播到多个观察者,不同于Observable有单独的执行环境,它应该没有单独的执行环境。

这些意味着什么呢?我认为有三点:

1、你可以订阅主題从它的流中拉取值。

2、你可以推送值到流通过调用它的next方法,记住,它也是Observer

3、你可以把subject当做observer传递到一个Observable

图表说明

代码举例

const subject$ = new Subject<number>();

const observer = {
    next: console.log
}

const observable$ = interval(1000);

setTimeout(() => {
    console.log("Subscribing first observer");    
    subject$.subscribe(observer);
}, 1000);

setTimeout(() => {
    console.log("Subscribing second observer");
    subject$.subscribe(observer);
}, 2000);

observable$.subscribe(subject$);

日志信息

可以看出第一个订阅者订阅后我们的observable$发出了0;一秒后增加了第二个订阅者,observable$发出1以后直接广播到了两个observer,所以打印出了两个1,后面的情况类似。

subject内部特点

1、每次一个新的observer订阅,这个subject会将此observer存储在一个observber数组中。

2、当新的值发出时(比如调用next方法),subject将循环observer数组,发送相同的值到这些observer,这就是广播,当出现错误或者complete时,也会同样循环发送错误或complete。

3、当一个subject完成时,所有的observer数组中的observer取消订阅。

4、当subject取消订阅时,订阅依旧是激活的;但是所有的观察者数组将无效,但它不会取消订阅。如果你尝试發一个值,那么将发生错误;所以当你需要处理subject或者它的观察者时,最好直接完成它。

5、当subject的观察者取消订阅时,它将从sbject的注册数组中移除。

单播和多播

单播简单理解就是发送值到一个指定的观察者,而多播就是能够发送值到多个观察者。这里有一个重要的概念就是Cold Observable和Hot Observable。这些知识我们以后有机会再分析。

需要指出的是,今天我们谈论的主体其实就是将单播Observable转化成了多播Observable。

再举一个多播的例子吧。

多播的情况发生在订阅执行 HTTP 请求的 observable,这种情况在 Angular 等框架中经常发生:通过多播 observable,您可以避免执行多个请求并与多个订阅者共享执行,这些订阅者将接收相同的值。

其他类型的subject:AsyncSubject, ReplaySubject, and BehaviorSubject

AsyncSubject特点

1、仅仅在完成时发送值

2、仅仅发送出它接受到的最后一个值

图表说明

代码举例

onst asyncSubject$ = new AsyncSubject();
asyncSubject$.next(1);
asyncSubject$.next(2);
asyncSubject$.next(3);
asyncSubject$.subscribe(console.log);
console.log('after subscribe nothing');
// ... nothing happening!
asyncSubject$.complete();

日志信息

可以看出,订阅以后吗,没有发出值,一直到完成后才发出值。

其他两种我们下次分析,欢迎讨论。

©2020 edoou.com   京ICP备16001874号-3