Libertus Chen-U
  1. 1 Libertus Chen-U
  2. 2 BREAK IN TO BREAK OUT Lyn
  3. 3 Time Bomb Veela
  4. 4 Hypocrite Nush
  5. 5 Last Surprise Lyn
  6. 6 かかってこいよ NakamuraEmi
  7. 7 Life Will Change Lyn
  8. 8 Flower Of Life 发热巫女
  9. 9 Warcry mpi
  10. 10 One Last You Jen Bird
2017-08-06 12:22:08

RxJS操作符——数据流的构建

了解了RxJS中的关键概念后,就需要去掌握各种各样的操作数据流的操作符了。这篇文章从最初的操作符开始分析——创建相关。


创建相关的操作符最明显的一个特点就是能够创造出一个Observable对象,但其实所有的操作符都会创造一个Observable对象,区别之处在于,创建类操作符不依赖于Observable源,而是依赖于不同类型的数据甚至不依赖任何数据就能完成创造。正是由于这个特性,大部分创造类操作符也都是静态操作符。下面就一一介绍。

从无构建数据流

create

首先介绍的就是最原始也是最初的创建操作符——create。这个操作符从无开始创建数据流,数据流动的逻辑完全由自己定义。其接受参数为封装数据流动逻辑的函数,这个函数接受观察者为参数,通过观察者的方法实现数据的流动。例子如下:

let source = Rx.Observable.create(function(observer) {
    observer.next('a');
      observer.next('b');
      observer.complete();
}) 
// a-b-|

构建空数据流

除了手动定义数据流动逻辑,各种各样的创建操作符给予了我们快捷生成特定类型数据流的能力。那么最简单的特定数据是什么呢?当然就是空数据了。

empty

该方法创建一个没有数据元素的数据流,并且会在被订阅时立刻结束。例子如下:

let source = Rx.Observable.empty();
// |

never

该方法同样创建一个没有数据元素的数据流,但永远不会结束。例子如下:

let source = Rx.Observable.never();
// ---------------

throw

同理,创建一个没有数据元素的数据流,但会在订阅时立刻抛出错误。例子如下:

let source = Rx.Observable.never();
// X

以上三种不产生具体数据的创建操作符虽然看上去没什么用,但其实有些类似于数学中的0和无穷,和其他数据流配合就会发挥很大的作用。


构建序列化数据流

有时候我们需要序列形式的数据(例如index)对目标数据进行标识后再差异化处理,RxJS提供了快捷产生序列化数据流的能力。

range

该方法创建一个发射有限长度的整数序列化数据流。接受两个参数,第一个参数为序列化整数的起始值,第二个参数为元素数量。例子如下:

let source = Rx.Observable.range(10, 3);
// 10-11-12-|

interval

除了手动建立序列化数据流的range外,RxJS还提供了根据时间来生成数据流的能力。该操作符创建一个无限长度的序列化数据流。其接受一个单位为毫秒的周期参数,序列数据从0开始按该周期流出,依次增加1。例子如下:

let source = Rx.Observable.interval(1000);
// ---0---1---2---.......

timer

在interval之上还有timer操作符,提供了更为灵活的按时间生成序列数据流的方法。该操作符接受两个参数,第一个参数表示订阅后的静默时长,该参数可以为毫秒数Number或者日期Date,即为等待这段时间后再流出数据。第二个参数同interval相同表示周期参数,不传入第二个参数时经过静默时间后送出0后就结束。例子如下:

let source = Rx.Observable.timer(0, 1000);
// 0---1---2---3---....

可以认为interval是timer的一种简写,如果timer第一个参数和第二个参数相等,就和interval完全相同了。

构建自定义数据流

虽然以上介绍的数据流都有特殊又重要的用途,但平时最常用的数据流还是普通数据组成的数据流了,RxJS定义了多种根据普通数据创建数据流的操作符,根据业务场景需要选择合适的操作符可以更快捷的生成数据流。

枚举型

of

当我们想进行多值的枚举输出时使用该操作符。可以传入任意数量的参数,每个参数对于数据流中的一个元素。例子如下:

let source = Rx.Observable.of("a", "b", "c");
// a-b-c-|

序列型

generate

先前我们已经提到了序列型产生数据流的方法,但实际项目中问题往往没有那么简单,很多情况下我们需要的序列并不是稳定连续的,甚至于不是数字的序列,为此我们需要自定义序列产生的逻辑,这就是该操作符的应用之处了。

该操作符类似于for循环,接受4个参数,分别对应于for循环的4个表达式。举例如下:

const result = [];
for (let i = 0; i < 10; i++) {
    result.push(i * i);
}

// result转化为Observable流出数据
let source = Rx.Observable.generate(
    0, // 对应于初始值
      val => val < 10, // 对应于循环条件
      val => val++ // 对应于循环后置计算
      val => val * val // 对应于循环主体逻辑流出数据
);

需要注意,除了第一个参数为值外,其余三个参数都应该是纯函数。

转化型

很多时候我们需要转化的数据流的数据已经有了既定的数据类型,例如数组中的数据等。我们希望RxJS能识别它们并直接转化为可用的数据流。

from

该方法可以将可迭代对象中的数据直接转化为数据流,在ES6新增了多种可迭代对象,使用该方法转化相当方便。例子如下:

let source = Rx.Observable.from([1, 2, 3]);
// 1-2-3-|

pairs

该方法针对传统的不可迭代的对象,同Map对象一样,每个键值对对应一个数据留出元素。

let source = Rx.Observable.pairs({a: 1, b: 2});
// ['a', 1]- ['b', 2]-|

fromPromise

该方法将Promise对象转化为数据流,如果Promise成功则留出数据并完成,失败则流出error。from中也拓展了该操作符。

let promise = new Promise(function(resolve, reject) {
  resolve('ok');
});
let source = Rx.Observable.fromPromise(promise);
//'ok'-|

fromEvent

该方法将事件对象转化为数据流。接受两个参数,第一个参数为绑定事件的DOM对象,第二个参数为需要转化的事件。例子如下:

let clicks = Rx.Observable.fromEvent(document, 'click');
//clickEvent对象-----……

fromEventPattern

fromEvent可以将事件数据转化为Obsrvable,但有一个限制就是事件机制的实现必须等价于浏览器事件或者Node的EventEmitter,而很多情况下我们需要自定义更为灵活的观察者模式去处理数据。为此就有了这个方法。该方法用来转化类事件,也就是观察者模式生成的数据为数据流。该方法接受两个参数,第一个参数为注册监听者的处理函数,第二个参数为移除监听者的处理函数。最常用的地方是将多个对象的多种事件转化为一个事件数据流。例子如下:

let addListeners = function(handler) {
  el.addEventListener('click', handler);
  el.addEventListener('mousemove', handler);
};
let removeListeners = function(handler) {
  el.removeEventListener('click', handler);
  el.removeEventListener('mousemove', handler);
};
let source = Rx.Observable.fromEventPattern(addListeners, removeListeners);

bindCallback

该方法准确来说不是一个操作符,因为他的输入和输出都是函数,输入函数的最后一个参数必须为回调函数。其作用就在于将该回调函数执行返回的值转化为Observable。

值得注意的一点是,输出函数返回的Observable被订阅之前,输入函数不会执行。

可选参数selector接受和回调一样的参数,其作用在于映射Observable流出的结果。实例如下:

someFunction((a, b, c) => {
  console.log(a); // 'a'
  console.log(b); // 'b'
  console.log(c); // 'c'
});

const boundSomeFunction = Rx.Observable.bindCallback(someFunction, (a, b, c) => a + b + c);
boundSomeFunction().subscribe(value => {
  console.log(value) // 'abc'
});

小结

以上就是在RxJS中最常用的数据流生成操作符,掌握了这些就可以自由的生成想要的流,但这只是使用数据流的第一步,掌握好这一步为前提,才能发挥其他操作符的强大功能。

-- EOF --

添加在分类「 前端开发 」下,并被添加 「RxJS」 标签。