RXJS 系列 04

每日前提

  1. 内容为学习后的自我总结。再次感谢博主的分享,附上原po链接: 原po链接

十分枯燥的各种 API 操作符

  1. 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 作用:建立轮询

  2. 处理二维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) 的特殊情况
      
  3. xxxAll + Map

  • concatMap(ob, { e, res, outObIndex, inObIndex}) 作用: 确保每一个request 会等前一个request 完成才做处理。 比如: 某些操蛋的大文件上传,必须要等上一个分片传输完毕才继续上传下一个
    • 参数解析: concatMap 还有第二个参数是一个selector callback,这个callback 会传入四个参数:
      • 外部 observable 送出的元素
      • 内部observable 送出的元素
      • 外部 observable 送出元素的 index
      • 内部observable 送出元素的index
  • switchMap:switch + map
  • mergeMap(func, {}, number): number控制并行数量。 merge + map
  • 总结:
    • concatMap用在可以确定内部的observable结束时间比外部observable发送时间来快的情境,并且不希望有任何并行处理行为,适合少数要一次一次完成到底的的UI动画或特别的HTTP request行为。
    • switchMap 用在只要最后一次行为的结果,适合绝大多数的使用情境。
    • mergeMap 用在并行处理多个observable,适合需要并行处理的行为,像是多个I/O 的并行处理。
  1. 实践: 自动填充 附上仓库链接
posted @ 2020-05-11 15:59  xyJen  阅读(98)  评论(0编辑  收藏  举报