订阅的自定义完整方法是否自行取消订阅?
Does a custom complete method of a subscription unsubscribe on its own?
我创建了一个 Observable:
public getData(): Observable<any> {
return this.getEndpoint()
.pipe(
switchMap((endpoint) =>
this.http.get<any>(endpoint)
),
take(1)
);
}
我订阅了可观察对象并执行了 HTTP 调用
this.getData().subscribe({
next: data => this.data = data,
complete: () => {
this.someActions();
},
});
由于 Observable 管道中的 take(1),Observable 在发出一个值后完成。所以在我们执行 someActions() 的地方调用了完整的方法。
由于此方法是自定义的,订阅是自行取消订阅,还是必须在完整方法中手动取消订阅?
编辑:
订阅的完整方法如何取消订阅?
您永远不需要取消订阅已完成的可观察对象。 Observables 通过对其观察者的 complete() 或 error() 调用完成。这是 observable 合约的一部分。
考虑以下示例。
const sub = interval(250).pipe(
take(4),
map(x => x + 1)
).subscribe({
next: console.log,
complete: () => console.log("This observable completed naturally"),
err: _ => console.log("This observable completed with an error")
});
console.log("Sub is closed, no need to unsubscribe? " + sub.closed);
setTimeout(() => {
console.log("Sub is closed, no need to unsubscribe? " + sub.closed);
}, 1250);
控制台输出:
Sub is closed, no need to unsubscribe? false
1
2
3
4
This observable completed naturally
Sub is closed, no need to unsubscribe? true
这表明将完成的可观察对象不需要取消订阅,也不会造成内存泄漏。问题在于 long-lived 的可观察对象(比如没有 take
、takeWhile
、takeWhen
等运算符的区间)。
例如,在 angular 中,只要组件存在,一些可观察对象就需要存在,但不再存在。它们链接到组件 life-cycle。问题是忘记取消订阅像这样的 observables(那些 不 complete
自己)会导致内存泄漏。
同步示例:
of("Hello There").subscribe({
next: console.log,
complete: () => console.log("This observable completed naturally"),
err: _ => console.log("This observable completed with an error")
});
您无需取消订阅此可观察对象。事实上,因为它 运行 是同步的,所以它会在您取消订阅之前关闭。
const sub = of(1).subscribe();
console.log(sub.closed); // output: true
退订所需示例:
const sub = interval(1000).subscribe(console.log);
setTimeout(() => {
console.log("Sub is closed: " + sub.closed);
sub.unsubscribe();
console.log("Sub is closed: " + sub.closed);
}, 60 x 60 x 1000);
这里我们启动一个 observable,然后我们等待 一个小时 看看它是否关闭。然后我们取消订阅并检查它是否已关闭。这个间隔 运行 永远 直到明确取消订阅。
控制台输出:
0
1
2
... [skipping ahead]
3596
3597
3598
3599
Sub is closed: false
Sub is closed: true
我创建了一个 Observable:
public getData(): Observable<any> {
return this.getEndpoint()
.pipe(
switchMap((endpoint) =>
this.http.get<any>(endpoint)
),
take(1)
);
}
我订阅了可观察对象并执行了 HTTP 调用
this.getData().subscribe({
next: data => this.data = data,
complete: () => {
this.someActions();
},
});
由于 Observable 管道中的 take(1),Observable 在发出一个值后完成。所以在我们执行 someActions() 的地方调用了完整的方法。 由于此方法是自定义的,订阅是自行取消订阅,还是必须在完整方法中手动取消订阅?
编辑: 订阅的完整方法如何取消订阅?
您永远不需要取消订阅已完成的可观察对象。 Observables 通过对其观察者的 complete() 或 error() 调用完成。这是 observable 合约的一部分。
考虑以下示例。
const sub = interval(250).pipe(
take(4),
map(x => x + 1)
).subscribe({
next: console.log,
complete: () => console.log("This observable completed naturally"),
err: _ => console.log("This observable completed with an error")
});
console.log("Sub is closed, no need to unsubscribe? " + sub.closed);
setTimeout(() => {
console.log("Sub is closed, no need to unsubscribe? " + sub.closed);
}, 1250);
控制台输出:
Sub is closed, no need to unsubscribe? false
1
2
3
4
This observable completed naturally
Sub is closed, no need to unsubscribe? true
这表明将完成的可观察对象不需要取消订阅,也不会造成内存泄漏。问题在于 long-lived 的可观察对象(比如没有 take
、takeWhile
、takeWhen
等运算符的区间)。
例如,在 angular 中,只要组件存在,一些可观察对象就需要存在,但不再存在。它们链接到组件 life-cycle。问题是忘记取消订阅像这样的 observables(那些 不 complete
自己)会导致内存泄漏。
同步示例:
of("Hello There").subscribe({
next: console.log,
complete: () => console.log("This observable completed naturally"),
err: _ => console.log("This observable completed with an error")
});
您无需取消订阅此可观察对象。事实上,因为它 运行 是同步的,所以它会在您取消订阅之前关闭。
const sub = of(1).subscribe();
console.log(sub.closed); // output: true
退订所需示例:
const sub = interval(1000).subscribe(console.log);
setTimeout(() => {
console.log("Sub is closed: " + sub.closed);
sub.unsubscribe();
console.log("Sub is closed: " + sub.closed);
}, 60 x 60 x 1000);
这里我们启动一个 observable,然后我们等待 一个小时 看看它是否关闭。然后我们取消订阅并检查它是否已关闭。这个间隔 运行 永远 直到明确取消订阅。
控制台输出:
0
1
2
... [skipping ahead]
3596
3597
3598
3599
Sub is closed: false
Sub is closed: true