RXJS 系列 04
每日前提
- 内容为学习后的自我总结。再次感谢博主的分享,附上原po链接: 原po链接
十分枯燥的各种 API 操作符
-
operator:
-
distinct 去重
-
distinctUntilChanged
- 最常见的状况是我们在做多方同步时。当我们有多个Client,且每个Client 有着各自的状态,Server 会再一个Client 需要变动时通知所有Client 更新,但可能某些Client 接收到新的状态其实跟上一次收到的是相同的,这时我们就可用distinctUntilChanged 方法只处理跟最后一次不相同的讯息
- 说人话:如果最新推送的状态跟最后一次状态相同,则此次状态不必推送,保留最后一次状态即可
-
catch
-
如果回传当前observable,造成的效果就是无限循环,可以用在断线重连的场景
var source = Rx.Observable.from(['a','b','c','d',2]) .zip(Rx.Observable.interval(500), (x,y) => x); var example = source .map(x => x.toUpperCase()) .catch((error, obs) => obs); // 将当前的ob回传 example.subscribe({ next: (value) => { console.log(value); }, error: (err) => { console.log('Error: ' + err); }, complete: () => { console.log('complete'); } }); source : ----a----b----c----d----2| map(x => x.toUpperCase()) ----a----b----c----d----X| catch((error, obs) => obs) example: ----a----b----c----d--------a----b----c----d--..
-
-
retry(number:Number)
- number:尝试几次
- 即时同步的重新连接,在连线断掉后,不断的尝试
-
retryWhen 作用:错误通知或是例外收集
-
repeat 作用:建立轮询
-
-
处理二维observable的operator:
Observable<Observable<T>> => Observable<T>
-
concatAll() 多个obs 按顺序执行,如果其中有个是无限的,那么下一次永不会执行
var click = Rx.Observable.fromEvent(document.body, 'click'); var source = click.map(e => Rx.Observable.interval(1000).take(3)); // 每次输出3个数,执行完了,才会执行下个observable var source = click.map(e => Rx.Observable.interval(1000)); // 一直执行,第二个ob 永不会执行 var example = source.concatAll(); example.subscribe({ next: (value) => { console.log(value); }, error: (err) => { console.log('Error: ' + err); }, complete: () => { console.log('complete'); } }); click : ---------c-c------------------c--.. map(e => Rx.Observable.interval(1000)) source : ---------o-o------------------o--.. \ \ \ \ ----0----1----2| ----0----1----2| take(3) ----0----1----2| concatAll() example: ----------------0----1----2----0----1----2--..
-
switch 切换。字面意思,只要目标条件出现,就切换到下一个observableobservable
- 在新的observable送出后直接处理新的observable不管前一个observable是否完成,每当有新的observable送出就会直接把旧的observable退订(unsubscribe),永远只处理最新的observable
var click = Rx.Observable.fromEvent(document.body, 'click'); var source = click.map(e => Rx.Observable.interval(1000)); var example = source.switch(); example.subscribe({ next: (value) => { console.log(value); }, error: (err) => { console.log('Error: ' + err); }, complete: () => { console.log('complete'); } }); click : ---------c-c------------------c--.. map(e => Rx.Observable.interval(1000)) source : ---------o-o------------------o--.. \ \ \----0----1--... \ ----0----1----2----3----4--... ----0----1----2----3----4--... switch() example: -----------------0----1----2--------0----1--...
-
mergeAll(number: Number)
- merge 他可以让多个observable 同时送出元素,mergeAll 也是同样的道理,它会把二维的observable 转成一维的,并且能够同时处理所有的observable
- number: 同时处理的observable 数量
var click = Rx.Observable.fromEvent(document.body, 'click'); var source = click.map(e => Rx.Observable.interval(1000)); var example = source.mergeAll(); example.subscribe({ next: (value) => { console.log(value); }, error: (err) => { console.log('Error: ' + err); }, complete: () => { console.log('complete'); } }); click : ---------c-c------------------c--.. map(e => Rx.Observable.interval(1000)) source : ---------o-o------------------o--.. \ \ \----0----1--... \ ----0----1----2----3----4--... ----0----1----2----3----4--... switch() example: ----------------00---11---22---33---(04)4--... 从Marble Diagram 可以看出来,所有的observable 是并行(Parallel)处理的,也就是说mergeAll 不会像switch 一样退订(unsubscribe)原先的observable 而是并行处理多个observable。以我们的范例来说,当我们点击越多下,最后送出的频率就会越快。 var click = Rx.Observable.fromEvent(document.body, 'click'); var source = click.map(e => Rx.Observable.interval(1000).take(3)); var example = source.mergeAll(2); //并行处理 2 个 observable example.subscribe({ next: (value) => { console.log(value); }, error: (err) => { console.log('Error: ' + err); }, complete: () => { console.log('complete'); } }); click : ---------c-c----------o----------.. map(e => Rx.Observable.interval(1000)) source : ---------o-o----------c----------.. \ \ \----0----1----2| \ ----0----1----2| ----0----1----2| mergeAll(2) example: ----------------00---11---22---0----1----2--.. 当mergeAll 传入参数后,就会等处理中的其中一个observable 完成,再去处理下一个。以我们的例子来说,前面两个observabel 可以被并行处理,但第三个observable 必须等到第一个observable 结束后,才会开始。 concatAll 就是 mergeAll(1) 的特殊情况
-
-
xxxAll + Map
- concatMap(ob, { e, res, outObIndex, inObIndex}) 作用: 确保每一个request 会等前一个request 完成才做处理。 比如: 某些操蛋的大文件上传,必须要等上一个分片传输完毕才继续上传下一个
- 参数解析: concatMap 还有第二个参数是一个selector callback,这个callback 会传入四个参数:
- 外部 observable 送出的元素
- 内部observable 送出的元素
- 外部 observable 送出元素的 index
- 内部observable 送出元素的index
- 参数解析: concatMap 还有第二个参数是一个selector callback,这个callback 会传入四个参数:
- switchMap:switch + map
- mergeMap(func, {}, number): number控制并行数量。 merge + map
- 总结:
- concatMap用在可以确定内部的observable结束时间比外部observable发送时间来快的情境,并且不希望有任何并行处理行为,适合少数要一次一次完成到底的的UI动画或特别的HTTP request行为。
- switchMap 用在只要最后一次行为的结果,适合绝大多数的使用情境。
- mergeMap 用在并行处理多个observable,适合需要并行处理的行为,像是多个I/O 的并行处理。
- 实践: 自动填充 附上仓库链接