20、Operators (操作符)
操作符是 Observable 类型上的方法,比如 .map(...)、.filter(...)、.merge(...),等等。当操作符被调用时,它们不会改变已经存在的 Observable 实例。相反,它们返回一个新的 Observable。
大家可以结合常用操作符的交互图 来学习如何使用:
操作符本质上是一个纯函数 (pure function),它接收一个 Observable 作为输入,并生成一个新的 Observable 作为输出。
下面我们创建一个自定义操作符函数,它将从输入 Observable 接收的每个值都乘以10:
function multiplyByTen(input) {
var output = Rx.Observable.create(function subscribe(observer) {
input.subscribe({
next: (v) => observer.next(10 * v),
error: (err) => observer.error(err),
complete: () => observer.complete()
});
});
return output;
}
var input = Rx.Observable.from([1, 2, 3, 4]);
var output = multiplyByTen(input);
output.subscribe(x => console.log(x));
21、Operators实例操作符
它是 Observable 实例上的方法。举例来说,如果上面的 multiplyByTen 是官方提供的实例操作符:
Rx.Observable.prototype.multiplyByTen = function multiplyByTen() {
var input = this;
return Rx.Observable.create(function subscribe(observer) {
input.subscribe({
next: (v) => observer.next(10 * v),
error: (err) => observer.error(err),
complete: () => observer.complete()
});
});
}
实例运算符是使用 this 关键字来指代输入的 Observable 的函数。这里的 input Observable 不再是一个函数参数,它现在是 this 对象,然后调用输出:
var observable = Rx.Observable.from([1, 2, 3, 4]).multiplyByTen();
observable.subscribe(x => console.log(x));
22、Operators静态操作符
它是直接附加到 Observable 类上的。静态操作符在内部不使用 this 关键字,而是完全依赖于它的参数。它们只接收非 Observable 参数,比如数字,然后创建一个新的 Observable ,而不是将一个输入 Observable 转换为输出 Observable.
一个典型的静态操作符例子就是 interval 函数。它接收一个数字(非 Observable)作为参数,并生产一个 Observable 作为输出:
var observable = Rx.Observable.interval(1000 /* 毫秒数 */);
还有一些组合操作符也是静态的,比如 merge、combineLatest、concat,等等。它们将多个 Observables 作为输入,而不仅仅是一个:
var observable1 = Rx.Observable.interval(1000);
var observable2 = Rx.Observable.interval(400);
var merged = Rx.Observable.merge(observable1, observable2);
23、Operators弹珠图
这是一张在官网找到的图片,它是用来描述数据流从开始到结束的一个过程,之所以把他拿出来是为了让大家能够更好的理解上面的逻辑,也让大家知道有这么样子的一张图官网起名叫做弹珠图。
24、Operators选择操作符
选择操作符就像上面看到的那样,他会一步一步的根据你的需求,找到最终你想要的一个操作符,具体请参考官网:选择操作符
25、Operators操作符分类
具体操作符分类请参考官网:操作符分类
26、Subject (主体)
大家记住一句话:Subject 既是 Observable,又是 Observer 。,为了方便理解这句话,大家看一下下面这两段代码:
var subject = new Rx.Subject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(1);
subject.next(2);
var subject = new Rx.Subject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
var observable = Rx.Observable.from([1, 2, 3]);
observable.subscribe(subject);
当对 subject 调用 subscribe 时,只是将 observer 添加到数组中。每当subject或 observable发出值时,它才会调用数组中每个next() 方法。
27、为啥要定义Subject (主体)概念
有下面两点原因:
-
Subject是一种能够发射数据给多个observer的Observable, Observable只能发射数据给一个observer, 所以说Subject是一种特殊类型的 Observable
var subject = new Rx.Subject(); subject.subscribe({ next: (v) => console.log('observerA: ' + v) }); subject.subscribe({ next: (v) => console.log('observerB: ' + v) }); subject.next(1); subject.next(2);
-
当使用 Subject 时,无论你何时 subscribe, 你永远都会得到相同的执行,这点不同于典型的 observable,每次 subscribe 都会开启有个新的执行。
const interval$ = Rx.Observable.interval(1000).take(7); const subject = new MySubject(); subject.map(value => `Observer one ${value}`).subscribe(value => { console.log(value); }); interval$.subscribe(subject); setTimeout(() => { subject.map(value => `Observer two ${value}`).subscribe(value => { console.log(value); }); }, 2000);
28、Subject派生(BehaviorSubject)
BehaviorSubject它保存了发送给消费者的最新值。并且当有新的观察者订阅时,会立即从 BehaviorSubject 那接收到这个最新值。
在下面的示例中,BehaviorSubject 使用值0进行初始化。
var subject = new Rx.BehaviorSubject(0);
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.next(1);
subject.next(2);
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(3);
29、Subject派生(ReplaySubject)
ReplaySubject 类似于 BehaviorSubject,它可以发送旧值给新的订阅者,但它还可以记录 Observable 执行的一部分。
当创建 ReplaySubject 时,你可以指定回放多少个值:
var subject = new Rx.ReplaySubject(3); // 为新的订阅者缓冲3个值
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(5);
除了缓冲数量,你还可以指定 window time (以毫秒为单位)来确定多久之前的值可以记录。 在下面的示例中,我们使用了较大的缓存数量100,但window time 参数只设置了500毫秒。
var subject = new Rx.ReplaySubject(100, 500 /* windowTime */);
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
var i = 1;
setInterval(() => subject.next(i++), 200);
setTimeout(() => {
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
}, 1000);
从输出可以看出,第二个观察者得到的值是3、4,这两个值是订阅发生前的500毫秒内发生的。
30、Subject派生(AsyncSubject)
AsyncSubject只有当 Observable 执行完成时(执行 complete()),它才会将执行的最后一个值发送给观察者。
var subject = new Rx.AsyncSubject();
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(5);
subject.complete();
21

被折叠的 条评论
为什么被折叠?



