rxjs 学习(1)-认识 rxjs 和理解 observables

原创
2018/12/28 09:19
阅读数 316

什么是 rxjs?

我查阅了一些资料,觉得比较通俗易懂的说法是:rxjs 是一个使用 Observable 的响应式编程库。它通过使用 observable 序列编写基于异步和事件的程序。核心类型是: Observable , 附属类型:Observer, Schedules, Subjects 和一些操作符 map,filter等。这些操作符可以把异步事件当作集合处理。我们可以把rxjs 当作用来处理事件的 lodash;

lodash 是一个一致性、模块化、高性能的 js 实用工具库,它的内部封装了很多字符串,数组,对象等常见类型的函数。

如何理解 Observable?

说到 Observable,可能我们得先了解一下异步编程的历史。

  • 最开始的时候,采用的是 callback 回调的方式,注册回调函数,等异步请求返回会后,把数据传入回调函数,对异步请求的结果进行处理。但是如果出现多个异步嵌套,就会出现可怕的回调地狱。
  • promise 的出现缓解了“callback hell”的问题。它承诺在一定的时间内,会完成事件或者是抛出错误。在代码执行时只需要监听这两种状态就可以了。但是也有弊端,同步和异步代码分离不好,代码可读性查,并且它一次只能处理一个事件,随着程序变大,promise 也会变得非常难管理。
  • 最新的 es2017 中出现了 async/await 的写法,它并不是一个新的功能,可以看作是 promise 的语法糖。但是依然没有改变同步代码和异步代码混用的局面。

对于数据传输的更具体地叙述可见:

此时 Observable 这种响应式的把同步异步代码都当作异步来操作的响应式编程就产生了。

rxjs 中的 Observable,说通俗一点,就是一个数据或是很多个事件组成在一起的数据流。rxjs 提供了很多操作这些数据流的方法,那就是操作数,比如 map,filter等。 现在我们来初步了解一下 Observable 吧。

关于 rxjs 的基础知识

既然上面说到了 Observable 是 rxjs 的核心类型,所以我们就来好好了解一下 observable 吧。

Observables 的产生来源

Observable 是数据流,它的产生有两种,一种是来自于已有的数据,将其转换成 observable; 还有一种是从无到有,直接创建 observable。这种感觉就像:我想要送给朋友一件礼物,可以选择自己手动 DIY, 也可以到淘宝买一份,然后包装。

从别的数据转换过来的方式有:

  • 来自一个或多个值,可以直接用 of(value) 转化: Rx.Observable.of('haha','xixi');
  • 来自数组, 使用 from(array) 转换: Rx.Observable.from([1,2,3]);
  • 来自事件, 使用 fromEvent(element,event) 转换: Rx.Observable.fromEvent(document.querySelector('button'), 'click');
  • 来自 Promise, 使用 fromPromise() 转换:Rx.Observable.fromPromise(fetch('/users'));
  • 来自 callback,bindCallback():Rx.Observable.bindCallback(fs.exists);

自己创建 observables 的有:

  1. 在外部产生新事件
import { Observable, BehaviorSubject, Subject } from 'rxjs';
const myObservable = new Subject();
myObservable.subscribe(value => console.log(value));
myObservable.next('haha');
  1. 在内部产生新事件
var myObservable = Rx.Observable.create(observer => {
  observer.next('haha');
  setTimeout(() => observer.next('xixi'), 1000);
});
myObservable.subscribe(value => console.log(value));

选择哪种方式需要根据场景。当你想要包装随时间推移产生值的功能时,普通的 Observable 就已经很好了。使用 Subject,你可以从任何地方触发新事件,并且将已存在的 observables 和它进行连接。

控制 Observables 数据流的流动过程

以在 input 框中输入 "hello world” 为例

const input = Rx.Observable.fromEvent(document.querySelector('input','input'));
  • 过滤掉小于3个字符长目标值
input.filter(event => event.target.value.length > 2)
    .map(event => event.target.value)
    .subscribe(value => console.log(value))// "hel"
  • 延迟事件
input.delay(200)
    .map(event => event.target.value)
    .subscribe(value => console.log(value));
  • 停止输入后 200ms 方能通过最新的那个事件
input.debounceTime(200)
    .map(event => event.target.value)
    .subscribe(value => console.log(value));
  • 取前 3 次事件流,在3次事件流后停止事件流
input.take(3)
    .map(event => event.target.value)
    .subscribe(value => console.log(value));// hel
  • 直到其他 observable 触发事件才停止事件流
const stopStream = Rx.Observable.fromEvent(document.querySelector('button','click'));
input.takeUntil(stopStream)
    .map(event => event.target.value)
    .subscribe(value => console.log(value));// hello ,点击才能看到

处理产生的值

还是以上个代码为例:输入 “hello world"

const input = Rx.Observable.fromEvent(document.querySelector('input'),'input');
// 传递一个值,不做处理
input.map(event => event.target.value)
    .subscribe(value => console.log(value));// 'h'

// 通过提取属性产生一个新的值
input.pluck('target','value')
    .subscribe(value => console.log(value));// 'h'
// 传递之前的两个值
input.pluck('target','value').pairwise()
    .subscribe(value => console.log(value));// ['h','he']

// 只会通过唯一的值
input.pluck('data').distinct()
    .subscribe(value => console.log(value));// 'helo wrd'

// 不会传递与上一个重复的值
input.pluck('data').distinctUntilChanged()
    .subscribe(value => console.log(value)); // 'helo world'

所以,综上可得,一个 observable 在程序中经过了产生 --> 控制流动方式 --> 最后产生的值的处理 --> 订阅 的四大过程。

展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部