Christian-Yang / Translate-and-save

Translate and save for my self
1 stars 0 forks source link

RxJs电子书学习笔记 #35

Open Christian-Yang opened 7 years ago

Christian-Yang commented 7 years ago

以下内容均是转载,原文地址:https://www.gitbook.com/book/buctwbzs/rxjs/details

本篇对应于官方的介绍篇,因英文介绍与gitbook文件名冲突,所以改了一下RxJS是一个通过使用可观察序列来构建异步基于事件的程序的库。它提供了一个核心类型:Observable、卫星类型(大概是这些类型均围绕于Observable,也就是Observable根基,而这些是辅助类型):Observer、Schedulers、Subjects)和操作符-衍生自一些数组方法,使得我们可以把异步事件以集合的方式进行处理。把RxJS当做一个针对事件的Lodash(一个JS库)。ReactiveX观察者模式迭代器模式和使用集合的函数式编程组合在一起,来满足这种管理事件序列的理想方式 RxJS中解决异步事件管理的基本概念如下: Observable可观察对象:表示一个可调用的未来值或者事件的集合。 Observer观察者:一个回调函数集合,它知道怎样去监听被Observable发送的 值 Subscription订阅: 表示一个可观察对象的执行,主要用于取消执行。 Operators操作符: 纯粹的函数,使得以函数编程的方式处理集合比 如:map,filter,contact,flatmapSubject(主题):等同于一个事件驱动器,是将一个值或者事件广播到多个观察 者的唯一途径。 Schedulers(调度者): 用来控制并发,当计算发生的时候允许我们协调,比如 setTimeout,requestAnimationFrame 第一个例子 通常你这样注册事件监听:

var button = document.querySelector('button');
button.addEventListener('click', () => console.log('Clicked!'));

使用RxJS创建一个可观察对象:

var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.subscribe(() => console.log('Clicked!'));
Christian-Yang commented 7 years ago

Purity 纯度; 纯洁

RxJX能够使用纯函数的方式生产值的能力使得它强大无比。这意味着你的代码不再 那么频繁的出现错误提示。 通常情况下你会创造一个非纯粹的函数,然后你的代码的其他部分可能搞乱你的程 序状态。

//这段代码中count=0是全局的,所以上一次的点击,会影响到下一次,比如上一次点击一次之后,
count就变成1了,但是上一次点击之后没有进行count重新设置为0的情况,所以会产生累加,
所以会出现问题。
var count = 0;
var button = document.querySelector('button');
button.addEventListener('click', () => console.log(`Clicked ${++
count} times`));

使用RxJS来隔离你的状态

//这里不会产生上面那样的累加情况,比如,第一次点击了一下,那么scan和subscribe就执行一次。
当点击第二次的时候count还是等于0,而不是上一次运行的结果。所以不会出现累加的情况
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.scan(count => count + 1, 0)
.subscribe(count => console.log(`Clicked ${count} times`));

scan操作符和数组中reduce方法的类似, 它需要一个传递给回调函数的参数值。 回调函数的返回值将成为下一次回调函数运行时要传递的下一个参数值。

===> scan函数的信息: http://rxmarbles.com/#scan http://reactivex.io/documentation/operators/scan.html http://xgrommx.github.io/rx-book/content/observable/observable_instance_methods/scan.html <===

Flow 流

RxJS有着众多的操作符,可以帮助您控制事件如何流入可观察对象observables(observables可以流入也可以露出事件)。 每秒最多只能点击一次的实现,使用纯JavaScript:

Christian-Yang commented 7 years ago
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();
} }
);

使用RxJS

var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.scan(count => count + 1, 0)
.subscribe(count => console.log(`Clicked ${count} times`));

其他的流操作符是filter, delay, debounceTime, take, takeUntil, distinct, distinctUntilChanged等等。

====> throttleTime函数的信息: http://reactivex.io/documentation/operators/debounce.html http://rxmarbles.com/#debounce <====

Values值

你可以通过可观察对象来转化值 下面的程序可以在每次点击鼠标时获取X坐标位置 纯的JS实现

Christian-Yang commented 7 years ago
var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', (event) => {
if (Date.now() - lastClick >= rate) {
console.log(++count + event.clientX)
lastClick = Date.now();
} }
);

RxJS实现

var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
.throttleTime(1000)
.map(event => event.clientX)
.scan((count, clientX) => count + clientX, 0)
.subscribe(count => console.log(count));

其他的值生产者还有 pluck, pairwise, sample 等等.

Christian-Yang commented 7 years ago

observable可观察对象 可观察对象以惰性的方式推送多值的集合。

               Single单值                             Multiple多值
pull拉         Function                                 Iterator
push推          Promise                                 Observable

下面的例子是一个推送1,2,3,4数值的可观察对象,一旦它被订阅1,2,3,就会被推 送,4则会在订阅发生一秒之后被推送,紧接着完成推送。

var 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');
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');

结果如下

Christian-Yang commented 7 years ago
just before subscribe
got value 1
got value 2
got value 3
just after subscribe
got value 4
done

Pull拉取 VS Push推送 拉和推是数据生产者和数据的消费者两种不同的交流协议(方式) 什么是"Pull拉"?在"拉"体系中,数据的消费者决定何时从数据生产者那里获取数 据,而生产者自身并不会意识到什么时候数据将会被发送给消费者。 每一个JS函数都是一个“拉”体系,函数是数据的生产者,调用函数的代码通过“拉 出”一个单一的返回值来消费该数据(return 语句)。 ES6介绍了iterator迭代器和Generator生成器——另一中“拉”体系,调用 iterator.next()的代码是消费者,可从中拉取多个值。

                        producer                                           Consumer
pull拉     Passive(被动的一方):被请求的时候产生数据          Active(起主导的一方):决定何时请求数据
push推   Active:按自己的节奏生产数据                            Passive:对接收的数据做出反应
                                                                       (处理接收到的数据)

什么是"Push推"?在推体系中,数据的生产者决定何时发送数据给消费者,消费者 不会在接收数据之前意识到它将要接收这个数据。 Promise(承诺))是当今JS中最常见的Push推体系,一个Promise(数据的生产者)发 送一个resolved value(成功状态的值)来注册一个回调(数据消费者),但是不同于函 数的地方的是:Promise决定着何时数据才被推送至这个回调函数。 RxJS引入了Observables(可观察对象),一个全新的"推体系"。一个可观察对象是一 个产生多值的生产者,并"推送给"Observer(观察者)。 Function:只在调用时惰性的计算后同步地返回一个值 Generator(生成器):惰性计算,在迭代时同步的返回零到无限个值(如果有可能