RxJS 应用探索

@豆丁 / 稿定前端开发实习生

分享内容

  • RxJS 是用来做什么的?
  • 实际应用(与 Vuex 对比)
  • 适用场景
  • Q&A

RxJS 是用来做什么的?

它能将异步的数据源封装成一个

可监听对象(Observable)

监听者(Listener)监听

并提供丰富的

操作符(Operator)

对数据流进行处理

视频网站

Observable:可观察对象,数据源

Observer:观察者,处理数据

// without RxJS

let btn = document.getElementById('btn');

btn.addEventListener('click', function(){
    console.log('You clicked the btn!');
}, false);


// with RxJS

let eventObservable = Rx.Observable.fromEvent(btn, 'click');

eventObservable.subscribe(() => {
    console.log('You clicked the btn!');
});

DOM事件

// without RxJS

setInterval(() => {
    console.log('do something regularly');
}, 1000)


// with RxJS

let intervalObservable = Rx.Observable.interval(1000);

intervalObservable.subscribe(() => {
    console.log('do something regularly');
})

定时任务

// without RxJS

fetch('/user')
    .then((res) => {
        // do something when response
    })


// with RxJS

let fetchObservable = Rx.Observable.fromPromise(fetch('/user'));

fetchObservable.subscribe((res) => {
    // do something when response
})

AJAX

// without RxJS

let socket = new WebSocket('wss://websocket.org');

socket.addEventListener('message', (event) => {
    // do something when response
});


// with RxJS

let fetchObservable = Rx.Observable.webSocket('wss://websocket.org');

fetchObservable.subscribe((res) => {
    // do something when response
})

WebSocket

Observable 创建方法

  • 单值:of, empty, never
  • 多值:from
  • 定时:interval, timer
  • 从事件创建:fromEvent
  • 从Promise创建:fromPromise
  • 回调函数创建:bindCallback
  • 自定义创建:create

视频网站

Observable:可观察对象,数据源

Observer:观察者,处理数据

Operator:加工数据

利用 Operator 实现事件委托

<div id="delegate">
    <span>span 1</span>
    <span>span 2</span>
    <span>span 3</span>
    <span>span 4</span>
    <span>span 5</span>
</div>

点击span时,输出span的内容。并且防止频繁点击,500毫秒内只能点击一次。

利用 Operator 实现事件委托

let delegate = document.getElementById('delegate');
let debonce = 500;
let lastTime = Date.now() - debonce;

delegate.addEventListener('click', (e) => {
    if (Date.now() - lastTime < debonce) return;
    if (e.target.tagName !== 'SPAN') return;

    console.log(e.target.innerHTML);
}, false);

利用 Operator 实现事件委托

let delegateObservable = Rx.Observable
    .fromEvent(document.getElementById('delegate'), 'click')
    .debounce(500)
    .filter(e => e.target.tagName === 'SPAN')
    .map(e => e.target.innerHTML)

delegateObservable.subscribe((val) => {
    console.log(val)
});

Operator 类型

  • 改变数据形态:map, mapTo, pluck
  • 过滤一些值:filter, skip, first, last, take
  • 时间轴上的操作:delay, timeout, throttle, debounce, audit, bufferTime
  • 累加:reduce, scan
  • 异常处理:throw, catch, retry, finally
  • 条件执行:takeUntil, delayWhen, retryWhen, subscribeOn, ObserveOn
  • 转接:switch
  • 整合:merge, combineAll

Think of RxJS as Lodash for events

Observable和Listener的结合

Subject

Subject 是一个可控 Observable

Subject 也是一个Listener

有什么用呢?

BehaviorSubject

缓存最新的数据

实际应用

(与Vuex对比)

Vuex

Vuex

RxJS

RxJS

RxJS

RxJS

问题出在哪?

  • Vue 和 RxJS 有交叉的部分
  • RxJS 并不是为数据层设计的

适用场景

复杂的UI操作

canvas 画图

canvas 画图

元素拖动

元素拖动

Q&A

RxJS

By 小新