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();
日志信息
可以看出,订阅以后吗,没有发出值,一直到完成后才发出值。
其他两种我们下次分析,欢迎讨论。