上次说了响应式中使用的设计模式,今天我们主要来看rxjs中实现响应式的三大件,Observable, subject 和 Subscription;
Observable--可观测序列
在第一节中介绍过 push 类型的系统和 pull 类型的系统,它们都可以产生值:
产生单个值 | 产生多个值 | |
---|---|---|
pull | function | iterator |
push | promise | ? |
在es6中promise已经被原生支持了,但是并没有一种原生的方法来实现push系统中产生多个值,于是Observable添补了这一空白。
// 创建一个observable
const observable = Rx.Observable.create(function(observer) {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => {
observer.next(4);
observer.complete();
},1000);
});
console.log('just before subscribe');
// 通过 subscribe 方法来获取 observable 上的值
observable.subscribe({
next: x => console.log('got value ' + x),
error: err => console.error('something wrong occurred: ' + err),
complete: () => console.log('done'),
});
console.log('just after subscribe);
这段代码执行后将会得到如下结果:
just before subscribe
got value 1
got value 2
got value 3
just after subscribe
got value 4
done
从结果可以看出通过一次订阅我们就可以拿到一个observable上所有推送过来的值,另外请注意看输出的顺序,1,2,3在 after之前,而4在after之后,这说明observable发出的值不一定都是异步或都是同步,什么时间可以取到值完全取决于以哪种方式发出。
上面代码中还有几个地方可能需要解释下:
- create:它实际上是Observable 的构造函数的别名,换句话说可以用 new Rx.Observable(...) 取代。
- observer:观察者,顾名思义,这个东西就是我们上一节讲过的观察者模式中的观察者,这里它是由rxjs负责给我们传递进来,实际上它就是我们在subscribe()中传入的那个对象。它有三个方法,next用来通知下一个值是什么;error 方法在 observable 上产生错误时通知观察者,complete方法用来通知观察者当前流上的值已经发射完毕。
-
subscribe: 它就是Observable类提供的方法,用来获取可观测序列上发出的值,接收一观察者作为参数。当然,上面的代码可以写成:
observable.subscribe(
x => console.log('got value ' + x), err => console.error('something wrong occurred: ' + err), () => console.log('done'),
);
第一个参数处理next通知,第二个参数处理error通知,第三个参数处理complete通知,我们还可以选择是否处理 error 通知和 complete通知,也就是说第二,三个参数还可以省略。当然rxjs内部还会把我们传入的参数处理成那个观察者对象。
以上代码中,我们实际已完成了observable 的创建(通过create),订阅(通过subscribe),执行(调用 next 和 complete)过程。除此之外在我们不需要订阅时,观察者还应该能够安全的退出。
subscription
这就是我们取消订阅时的所要用到的东西,上面的订阅代码完整的写法应该是:
const subscription = observable.subscribe({...});
它是我们订阅一个observable后获取到的,也就是subscribe方法的返回值,它上面有3个重要的方法。
- unsubscribe 顾名思义,取消订阅。
- add 添加另外一个subscription。在有多个subscription时我们可以通过这个方法将它们都链接起来,这样取消时只需要取消一个,而不必调用每个 subscription 的unsubscribe 方法。
-
remove 当然能添加必然可以移除。从当前的 subscription 上移除另一个 subscription
// 取消之前的订阅
subscription.unsubscribe();//重新订阅之前我们创建的observable,取消订阅时逐个调用它们的unsubscribe方法
const subscription1 = observable.subscribe({...});
const subscription2 = observable.subscribe({...});
const subscription3 = observable.subscribe({...});//重新订阅之前我们创建的observable,取消订阅时只调用一次unsubscribe
const sub$$ = observable.subscribe({...}).add(observable.subscribe({...})) .add(observable.subscribe({...}));
subject
它即是observable,也是observer,所以它即可以被 subscribe 又可以通过next,error,complete发射值。下面的例子中,我们给 Subject 添加了两个观察者,然后给它添加一些值:
const 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);
执行后的输出:
observerA: 1
observerB: 1
observerA: 2
observerB: 2
由于 Subject 也是一个 Observer ,所以你可以把他传递给一个 Observable 的subscribe方法:
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 来订阅这条 Observable
执行后输出:
observerA: 1
observerB: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3
通过上面的方法,我们基本上就借助 Subject 把一个单播的 Observable 转换成了多播的。这个示例仅仅是演示了一种将一个执行上下文分享给多个观察者的方法。
上面代码中有一个from方法,它的作用就是来创建一个可观测序列,类似于之前的create方法,但更加简洁,在rxjs中,它有个专门的名称叫个操作符,通过各种各样的操作符我们就可以实现可观测序列的创建,以及对序列中的数据进行各种各样的转换,可以说使用rxjs时我们大部分的时候都在使用各种各样的操作符。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。