前言
合并类操作符把多个数据流汇合为⼀个数据 流,但是汇合之前数据是怎样,在汇合之后还是那样;过滤类操作符可以 筛选掉⼀些数据,其中回压控制的过滤类操作符还可以改变数据传递给下 游的时间,但是数据本⾝不会变化,怎么进就怎么出。这⼀章会介绍RxJS 对于数据的转化处理,也就是让数据管道中的数据发⽣变化。
转化类和过滤类操作符都对数据做⼀些处理,但是过滤类做的处理是 筛选,决定哪些数据传递给下游,并不对数据本⾝做处理;⽽转化类操作 符不做过滤,会对每个具体数据做⼀些转化。
- 将每个元素用映射函数产生新的数据 —— map
- 将数据流中的每个元素映射为同一个数据 —— mapTo
- 提取数据流中每个数据的某个字段 —— pluck
- 产生高阶 Observable 对象 —— windowTime、windowCount、windowWhen、windowToggle和window
- 产生数组构成的数据流 —— bufferTime、bufferCount、bufferWhen、bufferToggel和buffer
- 映射产生高阶 Observable 对象然后合并 —— concatMap、mergeMap、switchMap、exhaustMap
- 产生规约运算结果组成的数据流 —— scan和mergeScan
对数据的转化可以分为两种:
- 对每个数据做转化。上游的数据和下游的数据依然是⼀对⼀的关系, 只不过传给下游的数据已经是另⼀个数据,⽐如上游传下来的是数据A, 传给下游的是数据f(A),其中f是⼀个函数,以A为输⼊返回⼀个新的数据。* 不转化单个数据,⽽是把数据重新组合。⽐如上游传下来的是A、 B、C三个数据,传给下游的是⼀个数组数据[A,B,C],并没有改变上游 数据本⾝,只是把它们都塞到了⼀个数组对象中传给下游。在RxJS中,创建类操作符是数据流的源头,其余所有操作符最重要的 三类就是合并类、过滤类和转化类。 使⽤RxJS解决问题绝⼤ 部分时间就是在使⽤这三种操作符,所以,⼀定要掌握这⼀章的知识,同时要及时复习⼀下前⾯的章节内容。
映射数据
![](https://i-blog.csdnimg.cn/blog_migrate/2a9892878c2e23b1ccab44004c4cc8b6.png)
假如上游的数据是A、B、C、D的序列,那么可以认为经过转化类操 作符之后,就会变成f(A)、f(B)、f(C)、f(D)的序列,其中f是⼀ 个函数,作⽤于上游数据之后,产⽣的就是传给下游新的数据。
1.map 对源 observable 的每个值应用投射函数
与JS不同之处是map这个操作符可以映射⼀段时间上异步产⽣ 的数据。因为RxJS的数据处理⽅式是“推”,每当上游推下来⼀个数据, map就把这个数据作为参数传给map的参数函数,然后再把函数执⾏的返回 值推给下游。
map除了必须要有的函数参数project,还有⼀个可选参数 thisArg,⽤于指定函数project执⾏时的this值。
const { of, interval } = rxjs;
const { map, } = rxjs.operators;
const source$ = of(3, 1, 4);
const mapFunc = function (value, index) {return `${value} ${this.separator} ${index}`;
};
const context = { separator: '=>' };
const result$ = source$.pipe(map(mapFunc, context));
result$.subscribe(console.log,
);
// 3 => 0
// 1 => 1
// 4 => 2
mapFunc这个函数是map的第⼀个参数,充当project的功能,同 时,map还有第⼆个参数context对象,如果⽤上这个参数,那么mapFunc在 每次执⾏的时候,this就是map的这个参数context。
注意
mapFunc的定义使⽤了不同的函数表达式,⽽不是箭头形式的函数定 义,因为箭头形式的函数定义⾥,this是绑定于定义环境的,map的第⼆个 参数也就不会起到任何作⽤。
这是map的⼀个⼩的功能细节,但是,并不建议使⽤,因为按照函数 式编程的原则,应该尽量让函数成为纯函数,如果⼀个函数的执⾏依赖于 this,那么就难以预料这个函数的执⾏结果,并不是什么好事。所以,虽然 我们知道map有这个功能,但要尽量避免使⽤它。
<