我每次订阅都需要退订吗

时间:2019-04-03 20:00:44

标签: rxjs

我正在尝试确定如何处理以下代码

let sub = myObservable.subscribe(
    v => doThing(v),
    e => handle(e),
    () => sub.unsubscribe(),
)

问题是 1.由于myObservable同步完成,因此此代码不正确,完成时将引发NPE。 2.即使我怀疑此处的退订呼叫是一种好习惯。我忍不住觉得没有必要,因为我在其他任何地方都没有看到它。

我已经读过这篇文章https://blog.angularindepth.com/why-you-have-to-unsubscribe-from-observable-92502d5639d0,但实际上,这比起初时更加困惑。

如果我愿意

let subA = myObservable.pipe(take(1)).subscribe()
let subB = myObservable.pipe(takeUntil(foo)).subscribe()

我是否不再需要取消订阅subA和subB?

这里的subC怎么样?

let subC = myObservable.pipe(finalize(() => cleanupOtherResources())).subscribe()

还是我必须将所有订阅添加到在每个subscribe()上调用BehaviorSubject的每个类的列表中,并立即取消订阅?

谢谢!

1 个答案:

答案 0 :(得分:1)

退订始终是最佳实践。如果您知道类的清除方法实际上在可观察的清除中发出,则可以使用takeUntil。并不能总是保证观察到的物体已经发射。在某些情况下,您知道可观察的对象肯定会至少发出一次,但是仍然有可能创建了泄漏。

假设可观察项将完成的问题是您不知道服务的内部是否返回了可观察的变化。如果您认为可观察对象是http请求并在请求结束时完成,则将来的重构会将可观察对象更改为缓存处理程序,这会导致内存泄漏,因为您没有取消订阅。

取消订阅还会取消所有正在进行的请求。

类似语句的问题

let sub = myObservable.subscribe(
    v => doThing(v),
    e => handle(e),
    () => sub.unsubscribe(),
)

如果myObservable立即像BehaviorSubject那样发出,则sub不确定。我会避免这样的自我退订,而应该对主题使用takeUntil。

const finalise$ = new Subject();

myObservable.pipe(takeUntil(finalise$)).subscribe(
    v => doThing(v),
    e => handle(e),
    () => { finalise$.next(); },
);

此代码保证可以自动退订。