发表在

角训练

如何自动取消订阅RxJs的可观察对象[教程]

如果你使用的是Angular,很有可能你也在使用RxJs。我在教Angular时经常遇到的一个问题是:我应该取消订阅所有这些可观察对象吗?如果有,什么时候,在哪里?

这篇文章将回答这些问题。

何时退订?

网上有很多关于如何退订的争论,但对于什么时候应该退订,肯定有一个共识。简单的答案是ngOnDestroy

为什么ngOnDestroy?因为无论如何从DOM中删除组件,这个方法总是会被调用。因此,这是唯一的方法,以确保您100%取消订阅无论如何正确。

下面是一个快速的代码示例来说明这一点:

import {Subscription} from 'rxjs';...潜艇:订阅构造函数(){
这一点。潜艇=someObservable。订阅(…);
/**
*生命周期钩子,当组件被销毁时取消所有订阅
* /
ngOnDestroy(): void {
this.subs。退订();

我应该一直退订吗?

是的。即使你使用一个完成的Observable,比如HttpClient请求,您应该取消订阅。

为什么?因为您的组件可以在订阅完成之前从DOM中删除。例如,假设您发出一个HTTP请求需要一些时间,而用户在请求仍在运行时单击导航离开该组件。恭喜你,你现在有了一个幽灵订阅,它可能会导致内存泄漏,因为这个可观察对象永远不会被取消订阅。

所以你应该经常退订ngOnDestroy

这不是很繁琐的工作吗?

如果你没有使用正确的工具,它可能是。我建议的第一件事是将所有订阅存储在一个数组中,这样就更容易遍历这些订阅并在以后取消订阅。

我一直在用沃德贝尔的SubSink实现为了解决这个问题。它是一个简单的类,存储你所有的订阅,并提供一个方法来取消所有的订阅:

导出类SomeComponent实现OnDestroy {
Private subs = newSubSink();

...
//简单语法
this.subs。水槽=可见美元.subscribe(…);
//与add()相同的工作
this.subs。添加(可见.subscribe美元(…));
//也可以添加多个订阅
this.subs。添加
可见美元.subscribe(……)
anotherObservable .subscribe美元(…)
);

...

//当组件失效时取消订阅
ngOnDestroy() {
this.subs。退订();

我们能做得更好吗?

当然,我们可以。如果你不想退订,我建议的第一个选择就是从一开始就不订阅。听起来很傻,但是用异步Pipe,你可以自动化订阅/获取数据/取消订阅机制,几乎不需要任何代码:

|异步”>

在上面的例子中,filteredEntries美元是Typescript类中准备的可观察对象,但没有订阅。我们让Angular在异步管

但是异步管道不为我工作,因为我想对我的Typescript代码中的数据做一些事情

这不是不使用的有效借口异步方法仍然可以注册一些副作用代码利用接线员:

filteredEntries美元: Observable = someObservable$.pipe(
利用(数据= >//对你的数据做些什么
);

这样我们就不是在Typescript中订阅,但当数据通过管道运行时,我们仍然可以做一些事情(双关语)。

如果我真的不能使用异步,仍然想写更少的代码怎么办?

这是我今天的最后一个技巧。和你一样,我也写累了ngOnDestroy它总是做同样的事情,所以我写了一个适配器类,只做这一切:

import {OnDestroy} from @angular/core;
import {SubSink} from './sub-sink';
/**
一个自动取消订阅所有可观察对象的类
*对象被销毁
* /
出口类UnsubscribeOnDestroyAdapter实现了OnDestroy
/**存储所有订阅的订阅接收器对象
Subs = newSubSink();
/**
*取消所有订阅的生命周期钩子
*当组件/对象被销毁
* /
ngOnDestroy(): void {
this.subs.unsubscribe ();

现在我所有有订阅的组件/服务/指令/管道都扩展了UnsubscribeOnDestroyAdapter。这样我就不用执行了ngOnDestroy在任何地方,该适配器都只执行一次。

我还使用SubSink,它也只声明了一次。现在我要做的是:

import {Component, OnInit} from '@angular/core';
import {UnsubscribeOnDestroyAdapter} from '../unsubscribe-on-destroy-adapter';
@ component({…})
导出类MyComponent扩展UnsubscribeOnDestroyAdapter
构造函数(){
超级();
this.subs.sink =someObservable .subscribe美元(…);

并完成了!使用上述技巧,我在Angular应用程序中实现了相当轻松的订阅管理。

要查看实际运行的此类代码示例,请参阅以下内容https://stackblitz.com/edit/unsubscribe-on-destroy?file=src%2Fapp%2Funsubscribe-on-destroy-adapter.ts

我叫betway必威滚球.我是谷歌的Angular开发专家,也是在角训练在那里我帮助开发团队学习并熟练使用Angular。

需要Angular的帮助吗?我们约个时间谈谈吧

如果你喜欢这篇文章,请鼓掌或分享。你的帮助我永远感激。

使用Medium应用程序

一个写着“在应用商店下载”的按钮,如果点击它将引导你进入iOS应用商店
一个写着“开始吧,谷歌Play”的按钮,如果点击它,就会引导你进入谷歌Play商店
Baidu