[转载升级V7]30 天精通 RxJS (07): Observable Operators & Marble Diagrams

ruby 复制代码
本文核心内容转载自https://blog.jerry-hong.com/series/rxjs/thirty-days-RxJS-07
原源代码用的Rxjs v5, 为了本人自己学习,参考官网改为v7版本

Observable 的Operators 是实践应用上最重要的部分,我们需要了解各种Operators 的使用方式,才能轻松实现各种需求!

昨天我们把所有建立Observable 实例的operators 讲完了,接下来我们要讲关于转换(Transformation)、过滤(Filter)、合并(Combination)等操作方法。先来让我们看看什么是Operator

什么是Operator?

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

javascript 复制代码
var people = of('Jerry', 'Anna');

function map(source, callback) {
    return new Observable((subscriber)=>{
        return source.subscribe(
            (value) => {
                try {
                    subscriber.next(callback(value));
                } catch (e) {
                    subscriber.error(e);
                }
            },
            (error) => { subscriber.error(callback(error));},
            () => { subscriber.complete(); }
        )
    })
}

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

helloPeople.subscribe(console.log);

// Jerry Hello~
// Anna Hello~

这里可以看到我们写了一个map 的函数,它接收了两个参数,第一个是原本的observable,第二个是map 的callback function。map 内部第一件事就是用new建立一个新的observable 并回传,并且在内部订阅原本的observable。

这里有两个重点是我们一定要知道的,每个operator 都会回传一个新的observable,而我们可以通过new的方法建立各种operator。

在RxJS 5 的实践中,其实每个operator 是透过原来observable 的lift 方法来建立新的observable,这个方法会在新回传的observable 物件内偷塞两个属性,分别是source 与operator,记录原本的数据源跟当前使用的operator。
其实lift 方法还是用new Observable(跟create 一样)。至于为什么要独立出这个方法,除了更好的封装以外,主要的原因是为了让RxJS 5 的使用者能更好的debug。关于RxJS 5 的除错方式,我们会专门写一篇来讲解!

其实RxJS 提供的各种operators 已经非常够用了,不太需要我们自己创造operator,这里只是想让大家先对operator 的建立有个基本的观念,之后在学习的过程中会比较轻松。

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

弹珠图 Marble diagrams

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

我们把描绘observable 的图示称为Marble diagrams,在网络上RxJS 有非常多的Marble diagrams,规则大致上都是相同的,这里为了方便撰写以及跟读者的留言互动,所以采用类似ASCII 的绘画方式。

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

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

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

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

|则代表observable 结束

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

在这个时间序当中,我们可能会发送出值(value),如果值是数字则直接用阿拉伯数字取代,其他的数据类型则用相近的英文符号代表,这里我们用interval举例

ini 复制代码
var source = interval(1000);

source的图形就会像这样

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

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

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

source的图形就会长像这样

scss 复制代码
(1234)|

小括号代表着同步发生。

另外的Marble diagrams 也能够表达operator 的前后转换,例如

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

这时Marble diagrams 就会长像这样

ini 复制代码
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 会带入每次发送出来的元素,然后我们回传新的元素,如下

javascript 复制代码
var source = interval(1000);
var newest = source.map(x => x + 2); newest.subscribe(console.log);
// 2
// 3
// 4
// 5..

用Marble diagrams 表达就是

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

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

mapTo

mapTo 可以把传进来的值改成一个固定的值,如下

ini 复制代码
var source = interval(1000);
var newest = source.mapTo(2); newest.subscribe(console.log);
// 2// 2// 2// 2..

mapTo 用Marble diagrams 表达

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

filter

filter 在使用上也跟阵列的相同,我们要传入一个callback function,这个function 会传入每个被送出的元素,并且回传一个boolean 值,如果为true 的话就会保留,如果为false 就会被滤掉,如下

javascript 复制代码
var source = interval(1000);
var newest = source.filter(x => x % 2 === 0); newest.subscribe(console.log);
// 0
// 2
// 4
// 6..

filter 用Marble diagrams 表达

sql 复制代码
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 篇!

相关推荐
小小竹子3 分钟前
前端vue-实现富文本组件
前端·vue.js·富文本
小白小白从不日白12 分钟前
react hooks--useReducer
前端·javascript·react.js
下雪天的夏风24 分钟前
TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
前端·javascript·typescript
diygwcom36 分钟前
electron-updater实现electron全量版本更新
前端·javascript·electron
Hello-Mr.Wang1 小时前
vue3中开发引导页的方法
开发语言·前端·javascript
程序员凡尘1 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js
编程零零七5 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
(⊙o⊙)~哦7 小时前
JavaScript substring() 方法
前端
无心使然云中漫步7 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者7 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js