30 天精通 RxJS (07): Observable Operators & Marble Diagrams

Observable 的 Operators 是实例应用上最重要的部份,咱们须要了解各类 Operators 的使用方式,才能轻松实现各类需求!javascript

这是【30天精通 RxJS】的 07 篇,若是还没看过 06 篇能够往这边走:
30 天精通 RxJS (06): 创建 Observable(二)%EF%BC%9A%20%E5%BB%BA%E7%AB%8B%20Observable(%E4%BA%8C).md)java

昨天咱们把全部创建 Observable 实例的 operators 讲完了,接下来咱们要讲关于转换(Transformation)、过滤(Filter)、合并(Combination)等操做方法。先来让咱们看看什么是 Operatorgit

什么是 Operator?

Operators 就是一个个被附加到 Observable 型别的函数,例如像是 map, filter, contactAll... 等等,全部这些函数都会拿到本来的 observable 并回传一个新的 observable,就像有点像下面这个样子github

var people = Rx.Observable.of('Jerry', 'Anna');

function map(source, callback) {
    return Rx.Observable.create((observer) => {
        return source.subscribe(
            (value) => { 
                try{
                    observer.next(callback(value));
                } catch(e) {
                    observer.error(e);
                }
            },
            (err) => { observer.error(err); },
            () => { observer.complete() }
        )
    })
}

var helloPeople = map(people, (item) => item + ' Hello~');

helloPeople.subscribe(console.log);
// Jerry Hello~
// Anna Hello~复制代码

JSBin | JSFiddle数组

这里能够看到咱们写了一个 map 的函数,它接收了两个参数,第一个是本来的 observable,第二个是 map 的 callback function。map 内部第一件事就是用 create 创建一个新的 observable 并回传,而且在内部订阅本来的 observable。函数

固然咱们也能够直接把 map 塞到 Observable.prototype学习

function map(callback) {
    return Rx.Observable.create((observer) => {
        return this.subscribe(
            (value) => { 
                try{
                    observer.next(callback(value));
                } catch(e) {
                    observer.error(e);
                }
            },
            (err) => { observer.error(err); },
            () => { observer.complete() }
        )
    })
}
Rx.Observable.prototype.map = map;
var people = Rx.Observable.of('Jerry', 'Anna');
var helloPeople = people.map((item) => item + ' Hello~');

helloPeople.subscribe(console.log);
// Jerry Hello~
// Anna Hello~复制代码

这里有两个重点是咱们必定要知道的,每一个 operator 都会回传一个新的 observable,而咱们能够透过 create 的方法创建各类 operator。ui

在 RxJS 5 的实例中,其实每一个 operator 是透过原来 observable 的 lift 方法来创建新的 observable,这个方法会在新回传的 observable 事件内偷塞两个属性,分别是 source(来源) 与 operator,记录本来的资料源跟当前使用的 operator。this

其实 lift 方法仍是用 new Observable(跟 create 同样)。至于为何要独立出这个方法,除了更好的封装之外,主要的缘由是为了让 RxJS 5 的使用者能更好的 debug。关于 RxJS 5 的除错方式,咱们会专门写一篇来说解!spa

这里咱们只是简单的实例 operator。若是以后实例上,想要不影响本来的 Observable 又可以自订 operator 能够参考官方的这份文件。(如今先不用看)

其实 RxJS 提供的各类 operators 已经很是够用了,不太须要咱们本身创造 operator,这里只是想让你们先对 operator 的创建有个基本的观念,以后在学习的过程当中会比较轻松。

在咱们开始介绍 RxJS 的 operators 前,为了能让咱们更好地理解各类 operators,咱们须要先订定一个简单的方式来表达 observable!

Marble diagrams

咱们在传达事物时,文字实际上是最糟的手段,虽然文字是咱们平时沟通的基础,但经常千言万语也比不过一张清楚的图。若是咱们能订定 observable 的图示,就能让咱们更方便的沟通及理解 observable 的各类 operators!

咱们把描绘 observable 的图示称为 Marble diagrams,在网路上 RxJS 有很是多的 Marble diagrams,规则大体上都是相同的,这里为了方便撰写以及跟读者的留言互动,因此采用相似 ASCII 的绘画方式。

咱们用 - 来表达一小段时间,这些 - 串起就表明一个 observable。

----------------复制代码

X (大写 X)则表明有错误发生

---------------X复制代码

| 则表明 observable 结束

----------------|复制代码

在这个时间序当中,咱们可能会发发送值(value),若是值是数字则直接用阿拉伯数字取代,其余的资料型别则用相近的英文符号表明,这里咱们用 interval 举例

var source = Rx.Observable.interval(1000);复制代码

source 的图形就会长像这样

-----0-----1-----2-----3--...复制代码

当 observable 是同步送值的时候,例如

var source = Rx.Observable.of(1,2,3,4);复制代码

source 的图形就会长像这样

(1234)|复制代码

小括号表明着同步发生。

另外的 Marble diagrams 也可以表达 operator 的先后转换,例如

var source = Rx.Observable.interval(1000);
var newest = source.map(x => x + 1);复制代码

这时 Marble diagrams 就会长像这样

source: -----0-----1-----2-----3--...
            map(x => x + 1)
newest: -----1-----2-----3-----4--...复制代码

最上面是本来的 observable,中间是 operator,下面则是新的 observable。

以上就是 Marble diagrams 如何表示 operator 对 observable 的操做,这能让咱们更好的理解各个 operator。

Marble Diagrams 相关资源:rxmarbles.com/

最后让咱们来看几个简单的 Operators!

Operators

map

Observable 的 map 方法使用上跟数组的 map 是同样的,咱们传入一个 callback function,这个 callback function 会带入每次发发送来的元素,而后咱们回传新的元素,以下

var source = Rx.Observable.interval(1000);
var newest = source.map(x => x + 1); 

newest.subscribe(console.log);
// 1
// 2
// 3
// 4
// 5..复制代码

用 Marble diagrams 表达就是

source: -----0-----1-----2-----3--...
            map(x => x + 1)
newest: -----1-----2-----3-----4--...复制代码

咱们有另一个方法跟 map 很像,叫 mapTo

mapTo

mapTo 能够把传进来的值改为一个固定的值,以下

var source = Rx.Observable.interval(1000);
var newest = source.mapTo(2); 

newest.subscribe(console.log);
// 2
// 2
// 2
// 2..复制代码

mapTo 用 Marble diagrams 表达

source: -----0-----1-----2-----3--...
                mapTo(2)
newest: -----2-----2-----2-----2--...复制代码

filter

filter 在使用上也跟数组的相同,咱们要传入一个 callback function,这个 function 会传入每一个被发送的元素,而且回传一个 boolean 值,若是为 true 的话就会保留,若是为 false 就会被滤掉,以下

var source = Rx.Observable.interval(1000);
var newest = source.filter(x => x % 2 === 0); 

newest.subscribe(console.log);
// 0
// 2
// 4
// 6..复制代码

filter 用 Marble diagrams 表达

source: -----0-----1-----2-----3-----4-...
            filter(x => x % 2 === 0)
newest: -----0-----------2-----------4-...复制代码

读者应该有发现 map, filter 这些方法其实都跟数组的相同,由于这些都是 functional programming 的通用函数,就算换个语言也有机会看到相同的命名及相同的用法。

实际上 Observable 跟 Array 的 operators(map, filter),在行为上仍是有极大的差别。当咱们的资料量很大时,Observable 的效能会好上很是多。咱们会有一天专门讲这个部份!

今日小结

今天咱们讲了 Observable Operators 的相关知识,有如下几个重点

  • 什么是 Operators
    • 如何创建 operator
  • Marble diagrams
  • Operators
    • map
    • mapTo
    • filter

不知道今天读者有没有收获呢?欢迎在下方留言给我,这是精通 RxJS 的第 07 篇!

相关文章
相关标签/搜索