RxJs——subject理解一

时间:2022-06-01 12:43:31

什么是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 Observable and an Observer 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

图表说明

RxJs——subject理解一

代码举例

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$);

日志信息

RxJs——subject理解一

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

subject内部特点

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

2、当新的值发出时(比如调用next方法),subject将循环observer数组,发送相同的值到这些observer,这就是广播,当出现错误或者conplete时,也会同样循环发送错误或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、仅仅发送出它接受到的最后一个值

图表说明

RxJs——subject理解一

代码举例

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();

日志信息

RxJs——subject理解一

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

 

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