当 .subscribe 里面有“副作用”时。比如我们在页面 A 请求了一个数据,拿到数据后会跳转特定路由,如果离开页面 A 时没有取消订阅,那么假设用户访问了页面 A 然后在请求完成前就离开了页面 A ,但是由于没有取消订阅,那么 .subscribe 里面的代码还是会执行,用户会被跳转到其它页面去。
当然,实际开发中,我们也可以为了省事,无论何时写 .subscribe 都加上取消订阅的处理。
能怎么减少需要取消订阅的场景吗
在 Angular 中,我们可以尽量在 html 中通过 async pipe 来直接使用 observable ,这样 html 销毁时 Angular 会处理取消订阅,我们就不用手动处理了,如下的代码就不需要再手动取消订阅了。
When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.
参考资料: https://www.thisdot.co/blog/best-practices-for-managing-rxjs-subscriptions
在刚开始学习使用 RxJS 时,如果没有仔细考虑取消订阅,那么很容易写出 bug ,请思考以下问题:
xxx$.subscribe()
后,我们需要取消订阅吗?没有取消订阅会有什么问题
举个例子,在进入页面 A 后,有个数据需要每 3 秒就请求一次,代码如下:
上面的代码中我们只写了
.subscribe
没有考虑取消订阅。当我们访问了页面 A 然后又通过前端路由跳转其它页面后,这里的轮询请求并不会停止,因为我们并没有取消订阅。那么哪些场景需要处理取消订阅呢?
.subscribe
里面有“副作用”时。比如我们在页面 A 请求了一个数据,拿到数据后会跳转特定路由,如果离开页面 A 时没有取消订阅,那么假设用户访问了页面 A 然后在请求完成前就离开了页面 A ,但是由于没有取消订阅,那么.subscribe
里面的代码还是会执行,用户会被跳转到其它页面去。当然,实际开发中,我们也可以为了省事,无论何时写
.subscribe
都加上取消订阅的处理。能怎么减少需要取消订阅的场景吗
在 Angular 中,我们可以尽量在 html 中通过 async pipe 来直接使用 observable ,这样 html 销毁时 Angular 会处理取消订阅,我们就不用手动处理了,如下的代码就不需要再手动取消订阅了。
确实需要手动取消订阅时,怎么写
unsubscribe 怎么写比较优雅呢,我们可以参考 antd-angular 中写法,见 ng-zorro-antd/empty.component.ts 。
你会不会想,如果我 subscribe 的是一个很复杂的 observable ,比如
merge(observable1, observable2).subscribe()
这种涉及了多个 observable 的,使用takeUntil
会把相关的 observable 都取消订阅吗?请放心!它会的!下面是个测试例子,当涉及多个 observable 时,createInterval
里面的unsubscribe
都会执行到。总结
.subscribe()
时要想清楚需要做取消订阅的处理不date$ | async
,这样就不用手动取消订阅了takeUntil(destroy$)
即可