因此,我对unsubscribe()方法还不清楚。
似乎合适的方法是在ngOnDestroy()生命周期方法中?所以我在下面的代码中做到了。但是,deleteFile()方法现在不会执行吗?
我在另一个线程中阅读了以下内容:(这是对的吗?)
“您不应90%地手动退订。在这种情况下, 在这种情况下,您正在使用服务来获取数据。如果此服务使用 http调用,因此HttpClient,可观察对象已经关闭 通话结束后,已关闭的可观察对象 取消订阅。”
那么我是否需要在此退订?谢谢
...
export class UploadComponent implements OnInit, OnDestroy {
private subscriptions: Subscription;
...
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
deleteFile(id: any) {
if (window.confirm("Are you sure you want to delete this file?")) {
const sub = this.fileCabinetService.deleteFile(id)
.subscribe(
res => {
...
},
error => {
...
}
);
this.subscriptions.add(sub);
}
}
答案 0 :(得分:1)
您误解了Subscription
和add
的工作方式。
当您subscribe
进入某个对象时,会得到一个Subscription
对象,您可以将其调用unsubscribe()
。这可以。但是,您没有正确分配值。您将Subscription
分配给const sub
,然后将其作为completion
块传递给add
。
像Subscription.add
的{{1}}块一样考虑finally
。无论try/catch
的结果如何,当它为Subscription
时,将执行传递给complete
的块。将此用于任何清理任务。
add
要回答有关何时subscriptions: Subscriptions[] = [];
ngOnDestroy() {
subscriptions.forEach((sub) => sub.unsubscribe());
}
deleteFile(id: any) {
const sub = this.fileCabinetService.deleteFile(id).subscribe(...);
this.subscriptions.push(sub);
sub.add(() => this.subscriptions.remove(sub));
}
的问题,实际上取决于unsubscribe
的工作。如果deleteFile
方法内部发出一个值(或一组值)的信号,然后完成,则预订将自动终止。如果尚未完成并悬而未决,则您的订阅将继续。
考虑以下情况:
deleteFile
此WallClock.subscribe((time) => console.log(time));
将永远不会终止,因为(大概)时间将无限期地持续。相反,您将需要手动控制终止时间。您可以通过以下几种方式执行此操作:
Subscription
如果您的/* Get the current time, but don't bother listening to updates. */
WallClock.pipe(take(1)).subscribe((time) => console.log(time));
/* Continually update with the current time as long as the component is on screen
— Requires setting `this.staySubscribed = false` when you're leaving */
WallClock.pipe(takeWhile(() => this.staySubscribed)).subscribe((time) => console.log(time));
/* Continually update until you remember to unsubscribe
— Requires remembering to unsubscribe and can get verbose with multiple subscriptions
- Call `this.subscription.unsubscribe()` later */
this.subscription = WallClock.subscribe((time) => console.log(time));
如此操作并且连续报告值而没有确定的完成条件,则应确保以某种方式终止订阅。可能是基于函数名的情况(基于函数的名称)deleteFile
,不需要您做任何事情。如果您想真正安全,Subscription
将为您确保安全。
答案 1 :(得分:1)
关于退订,您应该查看this answer中概述的takeUntil
模式。这是取消预订和避免内存泄漏的首选方法。您可以将代码重构为如下形式:
...
export class UploadComponent implements OnInit, OnDestroy {
private ngUnsubscribe = new Subject();
...
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
deleteFile(id: any) {
if (window.confirm("Are you sure you want to delete this file?")) {
this.fileCabinetService.deleteFile(id)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(
res => {
...
},
error => {
...
}
);
}
}
话虽如此,如果您订阅的是@angular/common/http
可观察的内容,则无需取消订阅,因为http
服务在以下情况下会调用complete()
数据返回。看看this implementation in the xhr back-end了解详情:
if (response.ok) {
responseObserver.next(response);
// TODO(gdi2290): defer complete if array buffer until done
responseObserver.complete();
return;
}
因此,对于@angular/common/http
个请求,不必担心。对于大多数其他人,请遵循takeUntil
模式。