简单学习rxjs中map、concatAll、concatMap、mergeAll、mergeMap、switchAll、switchMap
1、map
map和javascript中的数组的map方法类似,不过这里为了结合下面的demo,我先用map做一个我们不想要的效果:
const getData = (param) => {
return of(`return: ${param}`).pipe(
delay(Math.random() * 1000)
)
};
from([1, 2, 3, 4,5])
.pipe(
map(param => getData(param)),
)
.subscribe(val => console.log(val));
控制台输出是:
getData返回的是observable, 但是如果我想拿到返回的observable里面的值,怎么办呢?就是下面的方法了:
2、concatAll
javascript中数组也有一个方法叫做concat,实现的效果类似吧。
Flattens an Observable-of-Observables by putting one inner Observable after the other.
from([1, 2, 3, 4, 5])
.pipe(
map(param => getData(param)),
concatAll() // 比上个例子多出的部分
)
.subscribe(val => console.log(val));
输出结果是:
return: 1
return: 2
return: 3
return: 4
return: 5
多跑几次代码,每次都是这个输出顺序。
和上个demo相比,直接拿到了getData返回的observable中的值,因为concatAll有个flatten效果。不过可以把map和concatAll直接结合成一个操作符, 就是下面这个:
3、concatMap
Maps each value to an Observable, then flattens all of these inner Observables using concatAll.
这个操作符可以传递好几个参数,我学的比较简单,就用一个的:
from([1,2,3,4,5])
.pipe(
concatMap(param => getData(param))
)
.subscribe(val => console.log(val));
4、mergeAll
先跑代码,再分析吧:
from([1, 2, 3, 4, 5])
.pipe(map(
item => getData(item)),
mergeAll()
)
.subscribe(v => console.log(v));
多跑几次,就会发现每次的输出的顺序都是不一致的,并不是按照1 2 3 4 5的顺序输出的, 这点和concatAll不一致。为什么呢?
从上面的marble图可以看到,mergeAll接受2个observable,每个observable发射出来值之后,mergeAll之后产生的observable就直接emit了。而从concatAll的marble图可以看出,他等到反射完毕了先进入的observable发射出的所有值时候,才会发射后进入的observable发射的值。
其实也可以实现concatAll的效果,只要 mergeAll(1) 就可以了
map和mergeAll也可以和成一个操作符,就是下面这个了
5、mergeMap
Maps each value to an Observable, then flattens all of these inner Observables using mergeAll.
from([1, 2, 3, 4,5])
.pipe(
mergeMap(param => getData(param))
)
.subscribe(val => console.log(val));
6、switchAll
喜新厌旧
switch to a new observable.
it behaves like mergeAll. However, when a new inner Observable is emitted, switch unsubscribes from the earlier-emitted inner Observable and subscribes to the new inner Observable and begins emitting items from it.
from([1,2,3,4,5]).pipe(
map(param => getData(param)),
switchAll()
).subscribe(val => console.log(val));
每次运行的结果都是:
return 5
map之后产生的五个observable, 经过switchAll之后,由于五个observable的delay不同,所以还没来得及发射数据,就被最后的observable给‘踢’掉了。
和上面的差不多,map之后switchAll也可以合并成一个操作,就是下面的:
7、switchMap
from([1,2,3,4,5]).pipe(
switchMap(param => getData(param))
).subscribe(val => console.log(val));
结果和上面的是一样的了。
7、rxdart中的map
直接上代码:
import 'package:rxdart/rxdart.dart';
const a = [1, 2, 3, 4, 5];
void main() {
Observable(Stream.fromIterable(a))
.map((item) => item + 10)
.listen(print);
}
安装rxdart需要这么搞一下,在pubspec.yaml中加入:
dependencies:
rxdart: 0.21.0
参考文献:
https://medium.com/@luukgruijs/understanding-rxjs-map-mergemap-switchmap-and-concatmap-833fc1fb09ff
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-switchMap
http://semlinker.com/rxjs-merge-map-and-switch-map/