RxJS 和 数据驱动

数据驱动(data-driven) 是指将传递的数据和行为进行分离。这也是为什么RxJS能够以相同的范式来处理不同类型的数据源(比如数组,字符串,事件,AJAX请求等等)的核心原理。

  • 以数据作为中心,将数据从行为系统中分离出来,用数据去驱动业务
  • 没有数据,行为将不起作用,数据给行为带来升级,行为响应数据的变化,而不是等待数据的到来
  • 流(stream)只是一个传递过程,如果没有用户订阅,或者数据传递进来,流将保存闲置状态
RxJS 和 数据驱动_第1张图片
#1 stream如果没有被订阅将保持闲置状态.jpg

数据生产者 producers

数据的产生有不同的原因,这样造成数据源的来源有很多种情况。

  • 生产者有各种各样的形态和大小, Event Emitter 就是比较常见的一种生产者,它们用于响应鼠标点击或者网络请求,同时他们也是基于时间的数据源
  • 当处理不同类型的数据源,我们应当自然会想到使用不同类型的方式来处理。不如 event emitters 需要使用命名event handlers 来处理,Promises 需要一个连续传递的 thenable 函数来处理; setTimeout需要回调函数来处理; Arrays 需要通过循环来迭代数据

但是Rx对不同类型的数据进行了包装处理,这样我们可以以相同的范式来处理不同类型的数据源,也就是说

不同类型的数据源在事件驱动(或流驱动)的棱镜下观察都是一样的,
就好比Rx.Observable 是一个锤子,把其余所有的数据类型当作钉子

识别不同类型的数据源

数据源广义的可以分为以下几类:

  • Emitted Data
  • Static Data
  • Generated Data

1.Emitted Data

发生数据是一种外部与系统交互产生的结果。可以来自与用户交互,比如点击鼠标,也可以是系统事件,比如读取文件。

比如你请求数据,未来某个时间点,你接收到数据,对于这种情况, Promises 可能是一个好的解决方案。

2.static data

静态数据已经存在或者显示在系统(内存)中,比如 array ,string。人工的单元测试数据就划分到这一类型数据中。

3.Generated data

产生的数据是指间隔的或最终产生的数据,比如时钟每小时都会报时。

比如无限产生的数据,不可能将其全部存储在内存中,值应当动态的被创建和产生给需要的使用者。

数据类型的划分

根据以下2个维度可以将数据划分为4类:

  • 值的多少: 单值(比如数字), 多值(比如数组)
  • 数据的处理方式: 同步的, 还是异步的
RxJS 和 数据驱动_第2张图片
数据类型的划分.jpg

1.single-value && synchronous

这是最简单的数据类型,比如数字,一个对象,我们可以通过 Rx.Observable.of 将其转换为一个 Obserable类型。

但是一般处理简单类型的数据使用Observable,有点杀鸡用牛刀的味道,一般只有我们希望将简单类型的值和其它类型的流整合在一起时,才使用Obserable

2.multi-value && synchronous

我们可以将单值集合起来形成集合,主要是数组类型。

我们可以使用 Rx.Obserable.from 将集合类型转换为Obserable类型

3.single-value && asynchronous

对于异步的情况,正是RxJS大放异彩的地方

对于异步的情况,我们只能保证到吗在未来某个时间被处理,因此,后面的代码块不能依赖前面代码块的执行。

对于单值异步的情况,使用 Promises 进行处理最好了,在RxJS中可以使用 Rx.Observable.fromPromise() 将promises转换为Observable类型。

Rx.Observable.fromPromise($.ajax('/data'))

4. multi-value && aynchronous

这种类型的数据一般时间会作为数据来源的因子。比如DOM事件,不知道未来什么时候会产生。

对这种数据的处理我们需要 混合迭代器和promise模式,通常的处理方式是使用 EventEmitter 进行处理。

RxJS在javascript原有的EventEmitter的基础上对其进行了改进。可以使用 Rx.Observable.fromEvent() 将EventEmitter 转换为Observbale类型

PUSH-BASED && PULL-BASE MODEL

迭代器使用的 pull-based 模型, 而RXJS使用的是 push-based模型。

RxJS 和 数据驱动_第3张图片
#3数据推送和数据拉取模型.jpg
  • pull-based 对下面情况是非常拥有的: 当我们知道一个字能从计算后立即返回时。对于不知道值什么时候返回或者有没有值返回的情形,pull-based模型就失效了,比如鼠标点击,使用者是不知道下一次点击事件什么时候反生,或者发不发生
  • push-based模式中,生产者负责创建下一个数据,消费者只需要监听新的事件即可
RxJS 和 数据驱动_第4张图片
#3-1 push-based model.jpg

Observable && Observer

被观察者和观察者

  • 业务逻辑,比如值如何产生,怎么被发送归属于Observable,而所有的渲染细节,是否使用插件什么的处理逻辑归属于observer中的调度者
  • 要记住,无限事件发送,比如DO事件,将不会触发 complete() 方法,因此,取消订阅取决于使用者,可以采取手动取消订阅或者自动取消订阅机制
RxJS 和 数据驱动_第5张图片
#4被观察者和观察者.jpg

Observable 基本api

被观察者本质上一个函数

下面用简单的方式来描述observable

const observable = events => { // 时间队列
    const INTERVAL = 1 * 1000;
    let schedulerid;

    return { // 返回一个包含 'subscribe' 方法的对象
        subscribe: oberver => {  // 接收 observer 对象作为参数
            schedulerid = setInterval(() => {
                if (events.length === 0) { // 如果没有时间处理了
                    observer.complete();
                    clearInterval(schedulerid);
                    schedulerid = undefined;
                } else { // 如果有事件反生, 使用 observer.next()方法进行处理
                    observer.next(events.shift());
                }
            }, INTERVAL);

            return {
                unsubscribe: () => { // subscribe 方法返回一个unsubscribe 方法用于取消订阅
                    if (schedulerid) {
                        clearInterval(schedulerid);
                    }
                }
            };
        }
    }
}
RxJS 和 数据驱动_第6张图片
#4-1被观察者和观察者.jpg

总结

主要将了以下几个方面

  • RxJS采用了数据驱动的方式,数据和业务逻辑分离
  • RxJs对javascript的EventEmitter进行了改进,使其可以对事件进行推送
  • Push-based 和 Pull-based 方式的差异
  • 根据值的多少和处理方式2个维度,将数据源划分为4类
  • 简单Observable apis的介绍
    • Rx.Observable.of()
    • Rx.Observable.from()
    • Rx.Observable.fromPromise()
    • Rx.Observable.fromEvent()
  • Observable 和 Observer 之间的关系简单介绍

你可能感兴趣的:(RxJS 和 数据驱动)