如果从switchmap返回一个仍然订阅的observable,订阅是否可以保持订阅



考虑以下内容:

a$ = someObservable$.pipe(
switchMap(data => liveForEver$)
);
a$.subscribe();
a$.unsubscribe();

现在,顾名思义,liveForEver$已被代码的其他部分订阅。会不会是因为switchMap返回了一个"活的"可观测值,所以在取消订阅$后,$将继续订阅?

当定义了一个运算符时,它通常会在取消订阅时取消订阅子订阅。如果您创建了一个自定义运算符,但未能做到这一点,则可能会造成内存泄漏。考虑以下自定义运算符:

function timesTwo(input$: Observable<number>): Observable<number> {
return new Observable<number>(observer => {
input$.subscribe({
next: val => observer.next(val * 2),
complete: () => observer.complete(),
error: err => observer.error()
});
return {
// I should $input.unsubscribe()
unsubscribe: () => {/*Do Nothing*/}
}
});
}
function timesTwoPipeable<T>(): MonoTypeOperatorFunction<T> {
return input$ => timesTwo(input$);
}

在这里,我创建了自己的自定义rxjs运算符,它将输入流乘以2。所以1:

const subscription = interval(1000).pipe(map(x => x * 2))
.subscribe(console.log);
setTimeout(() => subscription.unsubscribe(), 5000);

和2:

const subscription = timesTwo(interval(1000))
.subscribe(console.log);
setTimeout(() => subscription.unsubscribe(), 5000);

和3:

const subscription = interval(1000).pipe(timesTwoPipeable())
.subscribe(console.log);
setTimeout(() => subscription.unsubscribe(), 5000);

所有这些都有相同的控制台输出,但2和3都订阅了间隔流,然后没有取消订阅。因此,后两个悄悄地造成了内存泄漏。您可以通过在所有三个示例中将interval(1000)更改为interval(1000).pipe(tap(_ => console.log("Still Alive")))来自己测试这一点。

所有内置的RxJS操作符都会自行清理。如果你自己建造,一定要这样做!


我在你的问题中注意到,你试图取消订阅一个可观察到的。我很惊讶这并没有造成错误。

我的结论是:

a$.subscribe();
a$.unsubscribe(); 

应该是:

const sub = a$.subscribe();
sub.unsubscribe();