首先概念澄清:
observable有两种数据类型:Clod and Hot
实际工作的两种情况:(一个Observable对象有不同Observer对象订阅,且不是同时订阅):
第一种:Hot 错过的数据就错过了,从订阅那一刻开始接受(生活中用电视机看电视节目)
第二种:Clod 需要完整的数据,错过的数据也需要获取(互联网看电视节目)
顺带一提:
Hot Observable实现的是多播;
Cold Observable实现的是单播。
在工作中最常见的疑惑:当通过http请求返回的observable我们需要对它做后续处理,订阅一个observer(observer是一个行为处理函数,包含对返回结果的一系列处理)。但是,当你使用subject的时候,发现他会源源不断的发送值,根本停不下来。
对于结束 Observable,释放内存的方式有三种方式:
-
第一种,Observable 完成值的发送,执行 Observable.onComplete()
-
第二种,Observable 发生错误,执行 Observable.OnError()
-
第三种,订阅者主动取消订阅,执行 subscription.unsubscribe()
对于Observable.onComplete()
和Observable.OnError()
,RxJS 自身会处理这两种情况,所以不需要在代码里再手动取消订阅释放内存。对于第三种方式,Observable 还在源源不断的发送值,订阅者想主动取消订阅,那就需要在代码里调用unsubscribe()
取消订阅释放内存。
在 Angular 项目中,常用到的订阅以及是否需要调用 unsubscribe() 取消订阅,有以下几种:
-
Angular 中通过 HttpClient 执行 Http Request 返回的 Observables,不需要调取消订阅。
-
Angular AsyncPipe,不需要调用 unsubscribe()取消订阅。
-
通过 Subject,BehaviorSubject,AsyncSubject,ReplaySubject 在各个 Component 之间通信,需要调用 unsubscribe()取消订阅。
-
RxJS 自带的一些操作符:take,takeWhile,first 等等,不需要调用 unsubscribe()取消订阅。
Http Request 返回的 Observables
Aangular 源码会处理完成的 Http Response Observables。
在 Http Response 结束时,如果 Request 成功会调用
responseObserver.complete()
,如果 Request 失败会调用responseObserver.error(response)
,complete()/error() 方法会结束当前 responseObserver。
Angular 中通过 HttpClient 执行 Http Request 返回的 Observables 是 Cold Observable 并且只发送一个值,Cold Observable 在值发送完成以后,RxJS 会执行 OnCompleted 方法,自动释放资源。
Angular Async Pipe
......
......
@Injectable()
@Pipe({name: 'async', pure: false})
export class AsyncPipe implements OnDestroy, PipeTransform {
......
private _subscription: SubscriptionLike|Promise<any>|null = null;
......
constructor(private _ref: ChangeDetectorRef) {}
ngOnDestroy(): void {
if (this._subscription) {
this._dispose();
}
}
......
......
在 ngOnDestroy 方法中,会执行this._dispose()
把 AsyncPipe 的订阅销毁。
通过四种 Subject 在各个 Component 之间通信
在 component 之间通信,我们会用到 Subject,BehaviorSubject,AsyncSubject,ReplaySubject 这四种 subject,它们都是Hot Observable,Hot Observable 不管有没有被订阅都会源源不断的发送值。如果订阅者要主动取消订阅,就必须手动调用unsubscribe() 取消订阅。在 Angular component 有个钩子函数:ngOnDestroy,在 commponet 被销毁之前执行,所以一般都是把 Subscription 的 unsubscribe 放在这个函数里执行,代码如下:
ngOnDestroy() {
this.subscription.unsubscribe();
}
RxJS 自带的一些操作符:take,takeWhile,first
在用这些操作符,比如 take(1),拿到 Observable 发送的第一个值之后,RxJs 会主动的停止当前的 Observable,也就是销毁当前 Observable,并不需要手动再调用 unsubscribe()取消订阅。