美文网首页
RxJS——repeat 和 share 两个和订阅有关的操作符

RxJS——repeat 和 share 两个和订阅有关的操作符

作者: du1dume | 来源:发表于2020-06-09 23:04 被阅读0次

    我们知道 takeWhile 操作符在条件函数不满足时立即触发流的 complete 事件,所表现出来的效果就是点击任何按钮都不再有任何反应。

    const addOneOrReset = (time = 1000) =>
    merge(
      interval(time).pipe(
        takeUntil(pauseBtnClick$),
        mapTo(addOne)
      ),
      resetBtnClick$.pipe(mapTo(reset))
    );
    
    const time$ = merge(
      startBtnClick$.pipe(mapTo(1000)),
      halfBtnClick$.pipe(mapTo(500)),
      quarterBtnClick$.pipe(mapTo(250))
    );
    
    const timer$ = time$.pipe(
      switchMap(addOneOrReset),
      startWith({ count: 0 }),
      scan((acc, current) => current(acc)),
      map(obj => obj.count),
      tap(v => setTxt(v))
    );
    
    const subscription = timer$
    .pipe(
      takeWhile(data => data <  5),
    )
    .subscribe(
      x => console.log(x),
      err => console.log(err),
      () => console.log("complete")
    );
    

    当我们点击开始按钮时,定时器流开始产生事件。由于 takeWhile 操作符的原因,到 5 时控制台将输出 complete。

    这里先说明下界面和控制台输出的数字为什么不一样。因为界面更新是在 tap 操作符做的,要先于 takeWhile 操作符。当界面更新为 5 时,takeWhile 操作停止了事件流。

    这时,我们再点击界面上的任何按钮都没有任何反应了。

    现在我们可以把这个定时器想象成一个 5 秒倒计时器,那我们的需求来了,现在的倒计时器是一次性的(除非刷新页面),如何能让它在一次倒计时完成后恢复到起始状态呢?这时,repeat 操作符闪亮登场了。

    下面只把变化的代码贴出来:

    const subscription = timer$
    .pipe(
      takeWhile(data => data <  5),
      repeat()
    )
    .subscribe(
      x => console.log(x),
      err => console.log(err),
      () => console.log("complete")
    );
    

    我们在 takeWhile 操作符下面添加了 repeat 操作符,这时的效果如下图:

    倒计时清零的需求完成了。这时我们还发现,控制台再也没有输出 complete ,这时因为我们没有给 repeat 传入任何参数,代表无限重复执行。大家可以自己试试传入了参数是什么效果。

    下面要重点说明的是,使用 repeat 操作符的位置将影响它的行为,这里交给读者自己去尝试,比如把 repeat 放在 takeWhile 的前面会是什么效果。使用 repeat 操作符的最佳实践是放在离订阅函数最近的位置。

    接下来,我们先来看看下面的代码会有什么输出:

    const timer$ = time$.pipe(
      switchMap(addOneOrReset),
      startWith({ count: 0 }),
      scan((acc, current) => current(acc)),
      map(obj => obj.count),
      tap(v => setTxt(v)),
    );
    
    timer$.subscribe(console.log)
    timer$.subscribe(console.log)
    

    我们订阅了两遍定时器流,控制台输出了两遍 0 ,这合情合理,每个订阅函数拥有独立的定时器流。但假如我们想让后来的订阅函数永远得到的是最新内容呢?就像订阅杂志,你得到杂志是从你订阅的时间以后的杂志,总不能把以前 20 年的杂志都给你吧?share 操作符可以帮你完成这个需求。我们只需在定时器流的最后加入 share,那么第二个 subscribe 函数将不会打印输出,这个就交给大家自己试试吧。

    const timer$ = time$.pipe(
      switchMap(addOneOrReset),
      startWith({ count: 0 }),
      scan((acc, current) => current(acc)),
      map(obj => obj.count),
      tap(v => setTxt(v)),
      share(),// <--- 这里
    );
    

    如有任何问题,更多内容请关注微信公众号“读一读我”(只给你实际工作用得上的干货)。

    相关文章

      网友评论

          本文标题:RxJS——repeat 和 share 两个和订阅有关的操作符

          本文链接:https://www.haomeiwen.com/subject/lasytktx.html