Angular何时取消订阅()?

时间:2019-01-18 17:04:55

标签: angular

因此,我对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);
 }
}

2 个答案:

答案 0 :(得分:1)

您误解了Subscriptionadd的工作方式。

当您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模式。