本文结构:
- 什么是
RxJS
-
RxJS
有什么特点 -
RxJS
核心概念
什么是RxJS
在javaScript中,我们可能会经常接触到类似于回调函数、Promise、Gender、async函数等异步编程方式,虽然以上的方式各有各的特点,但是我们需要更加强大的特性和更加优雅的写法.因此RxJS便是我们更好的选择.
Rx.JS
是英文 Reactive Extensions for JavaScript
的缩写.翻译成中文就是: JavaScript的响应式扩展.其主要的功能就是利用响应式编程的模式来实现JavaScript的异步式编程.
RxJS有什么特点
根据官方文档的介绍:
先写个简单的例子,注册事件监听器(事件代理):
var button = document.querySelector('button');
button.addEventListener('click', () => console.log('Clicked!'));
咱们用RxJS来实现这个功能(必须要引入Rxjs):
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.subscribe(() => console.log('Clicked!'));
以上代码大家应该是能看懂的,大概解释一下. Rx.Observable.fromEvent()
相当于创建了一个可观察对象Observable
,也就是监听的代理对象,subscribe是这个对象的一个方法,该方法返回这个监听的事件,subscribe
方法的参数是对观察对象返回值做出下一步操作(回调函数).
接下来介绍RxJS的特点:
纯净性
先看反面例子:
var count = 0;
var button = document.querySelector('button');
button.addEventListener('click', () => console.log(`Clicked ${++count} times`));
count作为一个全局变量,污染了全局环境,把应用状态搞的一团糟
下面是正面例子:
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.scan(count => count + 1, 0)
.subscribe(count => console.log(`Clicked ${count} times`));
scan
操作符的工作原理与数组的 reduce
类似。
每次回调函数运行后的返回值会作为下次回调函数运行时的参数.
流动性 (Flow)
反面例子:
var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', () => {
if (Date.now() - lastClick >= rate) {
console.log(`Clicked ${++count} times`);
lastClick = Date.now();
}
}); //实现控制一秒钟内最多点击一次
正面教材:
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.scan(count => count + 1, 0)
.subscribe(count => console.log(`Clicked ${count} times`));
这下觉得RxJS 用起来挺清爽的吧
RxJS核心概念
Observable
(可观察对象): 表示一个概念,这个概念是一个可调用的未来值或事件的集合。Observer
(观察者): 一个回调函数的集合,它知道如何去监听由 Observable 提供的值。Subscription
(订阅): 表示 Observable 的执行,主要用于取消 Observable 的执行。
Operators
(操作符): 采用函数式编程风格的纯函数 (pure function),使用像 map、filter、
concat、flatMap 等这样的操作符来处理集合。Subject
(主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。Schedulers
(调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout 或 requestAnimationFrame 或其他。
Observable (可观察对象)
Observables 是多个值的惰性推送集合
Observable
是RxJS的核心概念之一.它实际上就是可以被外界观察的一个对象.当本身的状态发生变化时,就会将其变化推送给外界观察它的对象,也就是 观察者对象.同时因为Observables
是多个值的惰性推送集合所以只有当使用一个观察者对象去订阅了它之后.它才会同步或异步地返回零到(有可能的)无限多个值.下面是使用RxJS
创建一个Observable
的方式
var observable = Rx.Observable.create(function subscribe(observer) {
var id = setInterval(() => {
observer.next('hi')
}, 1000);
});
上面实例创建了一个 Observable,它每隔一秒会向观察者发送字符串 'hi'.
Observer (观察者)
什么是观察者? - 观察者是由 Observable 发送的值的消费者。观察者只是一组回调函数的集合,每个回调函数对应一种 Observable 发送的通知类型:next、error 和 complete 。
简单来说,Observer就是使用Observable发送出来值的一个方法集合.当一个Observable发送出来值之后由Observer来决定如何的去使用它.而使用的方式就是通过回调函数.将Observable发送出来的值作为参数传入其中.让后在内部去使用.同时根据Observable发送出来的值不同.其调用的回调函数也不同.分别有next(下一步),error(报错),complete(结束).下面是使用Observer的方法:
observable.subscribe(observer);
要使用观察者,需要把它提供给 Observable 的 subscribe 方法
Subscription (订阅)
什么是 Subscription?
Subscription
是表示可清理资源的对象,通常是 Observable 的执行。Subscription 有一个重要的方法,即 unsubscribe,它不需要任何参数,只是用来清理由 Subscription 占用的资源。在上一个版本的 RxJS 中,Subscription 叫做 "Disposable" (可清理对象)。
Subscription(订阅)是使用observable.subscribe()创建一个观察者对象时.所返回的一个对象.它主要就是使用unsubscribe() 函数主动关闭Observer对Observable的监听订阅.其使用方法如下:
var observable = Rx.Observable.interval(1000);
var subscription = observable.subscribe(x => console.log(x));
// 稍后:
// 这会取消正在进行中的 Observable 执行
// Observable 执行是通过使用观察者调用 subscribe 方法启动的
subscription.unsubscribe();
Operators (操作符)
操作符是
Observable
类型上的方法,比如.map(...)、.filter(...)、.merge(...),
等等。当操作符被调用时,它们不会改变已经存在的Observable
实例。相反,它们返回一个新的Observable
,它的subscription
逻辑基于第一个Observable
。
操作符是函数,它基于当前的 Observable
创建一个新的 Observable
。这是一个无副作用的操作:前面的 Observable
保持不变。
就本质上而言Operators
就是一个纯粹的函数.它可以接收一个 Observable
作为输入.并在经过内部的一系列处理后返回一个新的Observable
作为输出.流向下一个操作.
Subject (主体)
什么是 Subject? - RxJS Subject 是一种特殊类型的 Observable,它允许将值多播给多个观察者,所以 Subject 是多播的,而普通的
Observables
是单播的(每个已订阅的观察者都拥有Observable
的独立执行)。
`Subject` 像是 `Observalbe`,但是可以多播给多个观察者。`Subject` 还像是` EventEmitters`,维护着多个监听器的注册表。
每一个Subject都同时是一个Observable
和Observer
.对于Subject
你可以使用subscribe
方法并指定一个观察者.也可以调用next(v)、error(e)
和complete()
来处理接受道到值.示例如下:
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 添加了两个观察者,然后给 Subject 提供一些值
Schedulers (调度器)
什么是调度器? - 调度器控制着何时启动 subscription 和何时发送通知。它由三部分组成:
- 调度器是一种数据结构。 它知道如何根据优先级或其他标准来存储任务和将任务进行排序。
- 调度器是执行上下文。 它表示在何时何地执行任务(举例来说,立即的,或另一种回调函数机制(比如 setTimeout 或 process.nextTick),或动画帧)。
- 调度器有一个(虚拟的)时钟。 调度器功能通过它的 getter 方法 now() 提供了“时间”的概念。在具体调度器上安排的任务将严格遵循该时钟所表示的时间。
调度器可以让你规定 Observable 在什么样的执行上下文中发送通知给它的观察者。