/*
* 一些过滤的操作符
* take 是从数据流中选取最先发出的若干数据
* takeLast 是从数据流中选取最后发出的若干数据
* takeUntil 是从数据流中选取直到发生某种情况前发出的若干数据
* first 是获得满足判断条件的第一个数据
* last 是获得满足判断条件的最后一个数据
* skip 是从数据流中忽略最先发出的若干数据
* skipLast 是从数据流中忽略最后发出的若干数据
*/
//冷Observable例子
const source$ = interval(100)
.pipe( take(4) );
// interval 和 JS 中的 setInterval 类似,参数为间隔时间,上面代码表示每隔0.1秒发出一个递增的整数(0,1,2...)
// source$即为从这些递增的整数中取出最先发出的4个,即0,1,2,3
setTimeout(() => {
source$.subscribe(res => {
console.log('observer1:', res);
});
}, 1000);
source$.subscribe(res => {
console.log('observer2:', res);
})
对于这个冷Observable有两个观察者,第一个观察者是1000ms后进行订阅,第二个观察者是马上进行订阅,根据冷Observable特点,所有订阅者拿到的值无关时机,都是一样的,打印结果都是0 1 2 3
//热Observable例子
//timer 则可以接收两个参数,第一个参数为发出第一个值需要等待的时间,
//第二个参数为之后的间隔时间。第一个参数可以是数字,也可以是一个 Date 对象,第二个参数可省。如:timer(100,200)表示在100m后开始产生第一个值0,后面每隔200ms产生递增的值
const source$ = (timer(0, 100)
.pipe(
take(3),
publish()
) as ConnectableObservable<number>);
source$.connect();
setTimeout(() => {
source$.subscribe(res => {
console.log('observer1:', res);
});
}, 100);
setTimeout(() => {
source$.subscribe(res => {
console.log('observer2:', res);
});
}, 1000);
上述这段代码则是利用RxJS里的多播publish操作符,将冷Observable转换成了热Observable。对于这个热Observable有两个观察者,第一个观察者是100ms后进行订阅,第二个观察者是1000ms后进行订阅,根据热Observable特点,订阅者拿到的值取决于订阅时机。最后打印结果为:
observer1: 1
observer1: 2
// 暖observable例子
// 多播share操作符,将冷Observable转换成了暖Observable
const source$ = interval(100)
.pipe(
take(3),
share()
);
setTimeout(() => {
source$.subscribe(res => {
console.log('observer1:', res);
});
setTimeout(() => {
source$.subscribe(res => {
console.log('observer2:', res);
});
}, 200);
}, 200);
setTimeout(() => {
source$.subscribe(res => {
console.log('observer3:', res);
});
}, 1000);
对于这个暖Observable有三个观察者,第一个观察者是200ms后进行订阅,第二个观察者是再过200ms后进行订阅,第三个观察者是1000ms进行订阅,此时生产者发送值已经结束。根据暖Observable特点,生产者从第一个订阅者订阅开始发送值,同时对于已经结束发送值后的订阅者也可以拿到完整的值。
最终打印结果是:
Subject是热Observable,Http请求是冷Observable。对于热Observable需要提前订阅,不然会错过发出的值。
在 Angular 项目中,常用到的订阅以及是否需要调用 unsubscribe() 取消订阅,有以下几种:
-
Angular 中通过 HttpClient 执行 Http Request 返回的 Observables,订阅这些 Observables 拿到 API 返回的数据,不需要调用 unsubscribe() 取消订阅。
-
Angular AsyncPipe,不需要调用 unsubscribe()取消订阅。
-
通过 Subject,BehaviorSubject,AsyncSubject,ReplaySubject 在各个 Component 之间通信,需要调用 unsubscribe()取消订阅。
-
RxJS 自带的一些操作符:take,takeWhile,first 等等,不需要调用 unsubscribe()取消订阅。