RxJS —— takeUntil

2019-11-22  本文已影响0人  芝麻香油

关于RxJS开篇是takeUntil,主要源于最近刚修复了一个神奇的bug。遂以takeUntil做为开篇。

看到bug是不是瞬间就激动、兴奋了。下面且看引起这个bug的代码:

// ...
this.stream$
  .pipe(
    takeUntil(this.compelete$),
    switchMap(id => 
      combineLatest(
        this.store.pipe(select(getAuth, { id, name: 'create' })),
        this.store.pipe(select(getAuth, { id, name: 'edit' })),
        this.service.getWhiteList()
      )
    ),
  )
  .subscribe(([res1,  res2, res3]) => {
     // ...
   });
// ...

上面这段代码,主体还是比较容易理解的,监听stream$变化,获取 createedit权限,以及白名单,然后 do something。这个时候 bug 就出现了,表象比较简单就是:白名单设置的权限有问题。

通过各种 debug,终于发现问题,正常使用时,断点会进入上述代码的subscribe,可是其他异常情况依然进入了上述代码的subscribe

自我检查:takeUntil 写了,destroy 写了,destroy 里 this.complete$.complete() 也写了。

那么问题出在哪里了呢?

原来就出在了 takeUntil 这里,takeUntil写在switchMap前面,那么takeUntil虽然结束了,但是switchMap这个流依然没被关闭。于是乎,讲takeUntil放在switchMap后面,尝试之后问题确实解决了。

this.complete$ 结束时,由takeUntil操作符返回的 observable 就算完成了,其订阅也会被自动取消。
然而,由于 stream$的订阅者所订阅的 observable 并非由 takeUntil返回,而是由 switchMap返回,所以当takeUntil的observable 完成时,stream$ 的订阅是不会被自动取消的。
switchMap的所有 observable 全部完成之前,stream$ 的订阅者都将始终保持订阅。所以,除非 combineLatest率先完成,否则这个订阅将不会结束

是不是所有的takeUntil都应该放在最后呢?

当然并不是所有的takeUntil都应该放在最后。

同时,项目上已经大量使用 rxjs,之前没有align过takeUntil应该放哪,在项目全局搜索会发现这种潜在的bug还有很多,于是乎发现了 rxjs-lint-rules 其中rxjs-no-unsafe-takeuntil,可以帮助检测出所有不规范的,然后逐一修复。

上一篇下一篇

猜你喜欢

热点阅读