欢迎指导与讨论:)
前言
本文是笔者翻译 RxJS 5.X 官网各类operation操作系列的的第一篇 —— transform转换。如有错漏,希望大家指出提醒O(∩_∩)O。更详细的资料尽在rxjs官网 【http://reactivex.io/rxjs/manual/overview.htm】与带有demo例子的网站【http://xgrommx.github.io/rx-book/content/observable】。
本文有关于transform操作的内容:buffer、bufferCount、bufferTime、bufferToggle、bufferWhen、concatMap、concatMapTo、exhaustMap、expand、groupBy、map、mapTo、merge、mergeMap、mergeMapTo、mergerScan、mergeAll、pairwise、partition、pluck、scan、switchMap、switchMapTo、window、windowCount、windowTime、windowToggle、windowWhen。
1. buffer —— 自定义分组
建立一个缓冲区(Observable),将数据源产生的值收集到缓冲区中,然后通过一些规则,让这些值重新发射。
var source = Rx.Observable.timer(0, 50) .buffer(function () { return Rx.Observable.timer(125); }) .take(3); // [0, 1, 2], [3, 4, 5], [6, 7]
2. bufferCount —— 根据数据量分组
建立一个缓冲区(Observable),将数据源收集到缓冲区中,然后根据参数n对数据源进行分组,每组有n个数据,最后把分组好的数据集合发射出来
var source = Rx.Observable.range(1, 6) .bufferCount(2); // [ 1, 2 ], [ 3, 4 ], [ 5, 6]
3. bufferTime —— 根据时间分组
建立一个缓冲区(Observable),将数据源收集到缓冲区中,然后根据时间参数n对数据源进行分组,在同一n毫秒下的数据为一组,然后把分组好的数据集合发射出来。
var source = Rx.Observable.timer(0,1000); //序列:0 1 2 3 ... var target = source.bufferTime(2500); //序列:[0,1,2] [3,4] ...
4. bufferToggle —— 根据自定义开始与结束分组
bufferToggle(open: Observable, () => close: Observalbe : Observalbe<T[]>)。(参考自资料)
const source$ = Rx.Observable.interval(500); const open$ = Rx.Observable.interval(1500); const close$ = Rx.Observable.interval(1000); const foo$ = source$.bufferToggle(open$, ( ) => { return close$; }); /** ---0---1---2---3---4---5---6---7---8---9----.... (source) -----------1-----------2-----------3--------... (open) --- ---x --- ---x --- ---x... (close) bufferToggle(open$, () => close$) ------------------([2,3])-----([5.6])-----([8,9])--... */
5. bufferWhen —— 根据自定义关闭函数进行分组
bufferWhen( closeFuc: function( ): Observable ): Observable<T[]>
每当关闭函数发射值时,为当前数据进行一次分组,并把这次分组后的数据组返回。
const open$ = Rx.Observable.interval(1000); const click$ = Rx.Observable.fromEvent(document, ‘click‘); var w = open$.bufferWhen(( ) => click$); w.subscribe(x => console.log(x)) // 每次点击都能进行一次分组 // 第二秒点击第一次:[0, 1, 2] // 第六秒点击第二次:[3, 4, 5, 6]
6. concatMap —— 数据遍历映射,并【依次】拼接
将数据源中的每项数据都执行一遍指定的函数,并且此函数需返回一个Observable,最后将各个运行函数后的Observable依次拼接起来。mergeMap是把运行后合并起来。
var source = Rx.Observable.of(1,2,3); var mf = function(item){ return Rx.Observable.range(item,3); }; var target = source.concatMap(mf); //序列:1 2 3, 2 3 4, 3 4 5
7. concatMapTo —— 数据遍历映射为特定的Observable,并【依次】拼接
与concatMap类似,但是将每个值映射到的是相同内容Observable
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.concatMapTo(Rx.Observable.interval(1000).take(4)); result.subscribe(x => console.log(x)); // 每次点击都映射为 interval(1000).take(4)
8. exhaustMap —— 在有空时才进行数据映射
将数据源中的每项数据都执行一遍指定的函数,并且此函数需返回一个Observable,此时立即执行当前的Observable的subscribe函数,在subscribe函数执行期间,若数据源有新的数据到达也不会执行所指定的函数并返回Observable。即只有当,当前Observable.subscribe执行完毕,才接受下一个数据,并重复上述过程。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.exhaustMap((ev) =>Rx.Observable.interval(1000).take(4)); result.subscribe(x => console.log(x)); // 每次点击,都会在4秒内,产生[0, 1, 2, 3] // 在产生期间,新的点击不会再产生[0,1,2,3]
9. expand —— 递归地数据映射
expand会把上次产生的值传给自己,从而递归。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var powersOfTwo = clicks .mapTo(1) .expand(x => Rx.Observable.of(2 * x).delay(1000)) .take(10); powersOfTwo.subscribe(x => console.log(x)); // 1, 2, 4, 8, 16, 32, 64, 128 ...
10. groupBy —— 根据指定条件对数据源进行分组
把数据源根据指定的条件函数进行分组,并得到Observable group。函数所返回的字符串,将作为每个分组(group)的key值。group可以被订阅。
var source = Rx.Observable.timer(0,1000);//序列:0 1 2 ... var gf = function(item){ return item %2 === 0 ? "EVEN":"ODD"; // 分为EVEN与ODD组 } var target = source.groupBy(gf); target.subscribe(x => { if ( x.key === ‘EVEN‘ ) { // 根据key值选择group x.subscribe( x => console.log(x)) } });
11. map —— 对数据源每项进行特定转换操作
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var positions = clicks.map(ev => ev.clientX); positions.subscribe(x => console.log(x)); // 每次点击输出鼠标点击的位置
12. mapTo —— 对数据源每项都转换为指定的值/其他
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var greetings = clicks.mapTo(‘Hi‘); greetings.subscribe(x => console.log(x)) // 每次点击都输出‘HI‘
14. merge —— 对多个数据源进行合并
将多个Observable进行合并,每当其中一个Observable发射值时,都会被observer所收到。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.merge(Rx.Observable.interval(1000)); result.subscribe(x => console.log(x)); // 不点击的情况下,每秒输出i, i为从零到n // 点击一下,马上输出 $mouseEvent
14. mergeMap —— 对数据源每项进行特定转换操作,然后合并
对数据源的所产生的所有值,经过函数转换为Observable,然后合并所有的Observable到一个流中。concatMap则是对数据源的每项,经过函数转换为Observable然后合并这些Observable到一个流中。
// mergeMap var letters = Rx.Observable.of(‘a‘, ‘b‘, ‘c‘); var result = letters.mergeMap(x => Rx.Observable.interval(1000).map(i => x+i) ); result.subscribe(x => console.log(x)); // 每秒输出 ‘ai bi ci‘ i未从0到n // concatMap var letters = Rx.Observable.of(‘a‘, ‘b‘, ‘c‘); var result = letters.concatMap(x => Rx.Observable.interval(1000).map(i => x+i).take(3) ); result.subscribe(x => console.log(x)); // 每秒依次输出 a0, a1, a2, b0, b1, b2, c0, c1, c2
15. mergeMapTo—— 对数据源每项进行特定转换操作,然后合并
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.mergeMapTo(Rx.Observable.interval(1000)); result.subscribe(x => console.log(x)); // 每次点击都会产生一个新的observabl计时器,这个observabl会被合并到同一个流中
16. mergeScan —— 暂无
17. mergeAll —— 将高阶Observable化为一阶
mergeAll能将高阶Obervable(能产生新Observable的Observable),全部扁平化(化为一阶),并把这些Observable合并到一起,oberver能够接收任意一个Observable所产生的值。它也能接收一个参数,表示当前时刻能merge的最大数量的Observable。与mergeMap/mergeMapTo的不同,mergeAll合成的是高阶Obserbable,mergeMap/mergeMapTo是直接合并一阶Observable。
// mergeAll无参数的情况 var clicks = Rx.Observable.fromEvent(document, ‘click‘); var higherOrder = clicks.map((ev) => Rx.Observable.interval(1000)); var firstOrder = higherOrder.mergeAll(); firstOrder.subscribe(x => console.log(x)); // 每次点击都能产生一个新 Observable // mergeAll把这些Observable合并到同一个Observable上 // mergeAll有参数的情况 var clicks = Rx.Observable.fromEvent(document, ‘click‘); var higherOrder = clicks.map((ev) => Rx.Observable.interval(1000).take(5)); var firstOrder = higherOrder.mergeAll(2); firstOrder.subscribe(x => console.log(x)); // 每次点击都能产生一个新 Observable // 但每个时刻只接收2个Observable,并把它们合并到一起 // 在队列中等待的Observable会在当前Observable数量小于2时加入
18. pairwise —— 组合当前Observable的所发生每个值
pairwise把当前Observable所发生的每个值,组合为一个含有两个值的数组,数组第一个值为当前项的值,数组第二个值为当下一项的值。
var a = Rx.Observable.interval(1000); var b = a.pairwise(); b.subscribe(x=>console.log(x)) // 依次输出:[1, 2], [2, 3], [3, 4], [4, 5], ....
19. partition —— 把当前Observable分隔为两组Observable
partition能根据指定条件对当前Observable分隔为两组,符合情况的为一组,不符合情况的为一组,与groupBy类似。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var parts = clicks.partition(ev => ev.target.tagName === ‘DIV‘); var clicksOnDivs = parts[0]; // 组1 var clicksElsewhere = parts[1]; // 组2 clicksOnDivs.subscribe(x => console.log(‘DIV clicked: ‘, x)); clicksElsewhere.subscribe(x => console.log(‘Other clicked: ‘, x));
20. pluck —— 根据key值提取Observable所产生的值的value
pluck能根据key值,提取Observable所产生的值(需要为一个对象)的value,我们能够传入多个key值,则会深层地获取value。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var tagNames = clicks.pluck(‘target‘, ‘tagName‘); tagNames.subscribe(x => console.log(x)); // 点击哪里,就输出哪的tagName --> 相当于输出$event.target.tagName
21. scan —— 对Observable值的进行累积操作
对Observable所发射的值进行累积操作,如累加累乘等,性质与原生js的reduce类似。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var ones = clicks.mapTo(1); var seed = 0; var count = ones.scan((acc, one) => acc + one, seed); count.subscribe(x => console.log(x)); // 每次点击输出:1, 2,3, 4....
22. switchMap —— 对Observable进行转换,并刷新当前Observable
switch接收一个函数,该函数会返回一个Observable,每当该函数又生成一个新的Observable时,新产生的Observable把上一个产生的Observable替换掉。即,有重新开始的意思。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.switchMap((ev) => Rx.Observable.interval(1000)); result.subscribe(x => console.log(x)); // 每次点击 会重新 从0到n开始输出
23. switchMapTo —— 对Observable进行指定转换,并刷新当前Observable
同上,只是switchMapTo直接接收一个指定的Observable作为参数,而swicthMap接收一个生成Observable的函数。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.switchMapTo(Rx.Observable.interval(1000)); result.subscribe(x => console.log(x)); // 每次点击会重新从0到n开始输出
24. window —— 产生新的Observable
window能产生新的Observable。因此整个调用window的表达式,实际上是一个高阶Observable(能产生Obervable的Observable, groupBy表达式也是高阶)。高阶Observable可以用mergeAll处理。
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var interval = Rx.Observable.interval(1000); var result = clicks.window(interval) .map(win => win.take(2)) // each window has at most 2 emissions .mergeAll(); // flatten the Observable-of-Observables result.subscribe(x => console.log(x)); // 每次点击 都往流中加入一个定时器
25. windowCount —— 根据 数量间隔 产生不同的Observable
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.windowCount(3) .map(win => win.skip(1)) // skip first of every 3 clicks .mergeAll(); // flatten the Observable-of-Observables result.subscribe(x => console.log(x));
26. windowTime —— 根据 时间间隔 产生不同的Observable
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks.windowTime(1000) .map(win => win.take(2)) // each window has at most 2 emissions .mergeAll(); // flatten the Observable-of-Observables result.subscribe(x => console.log(x));
27. windowWhen —— 根据参数产生不同的Observable
var clicks = Rx.Observable.fromEvent(document, ‘click‘); var result = clicks .windowWhen(() => Rx.Observable.interval(1000 + Math.random() * 4000)) .map(win => win.take(2)) // each window has at most 2 emissions .mergeAll(); // flatten the Observable-of-Observables result.subscribe(x => console.log(x));