关于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$变化,获取 create,edit权限,以及白名单,然后 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,可以帮助检测出所有不规范的,然后逐一修复。











网友评论