Angular / RxJS我应该取消订阅每个ajax电话吗?

时间:2018-01-24 19:19:51

标签: ajax angular rxjs

我应该取消订阅每个ajax电话吗?根据RxJS合同,我应该。因为AJAX调用不是流或事件,所以一旦完成它们就完成了。在这种特殊情况下,根本使用RxJS的原因是什么?加班它变成了混乱(我知道关于takeUntil,这不是重点)。

public remove(data: IData): void {
  // unsubscribe from the previous possible call
  if (this.dataSubscription &&
      this.dataSubscription.unsubscribe) {
    this.dataSubscription.unsubscribe();
  }
  this.dataSubscription = this.dataService
    .delete(data.id)
    .subscribe(() => {
      this.refresh();
    });
}

public ngOnDestroy(): void {
  // unsubscribe on deletion
  if (this.dataSubscription &&
      this.dataSubscription.unsubscribe) {
    this.dataSubscription.unsubscribe();
  }
}

优于简单承诺的优势是什么,在执行后看起来更干净,更容易被破坏?

public remove(data: IData): void {
  this.dataService
    .delete(data.id)
    .then(() => {
      this.refresh();
    });
}

这是DataService代码

@Injectable()
export class DataService {
  constructor(private _httpClient: HttpClient) { }

  public delete(id: number): Observable<IModel> {
    return this._httpClient.delete<IModel>(`${this._entityApiUrl}/${id}`);
  }
}

3 个答案:

答案 0 :(得分:6)

通常您不需要取消订阅HttpClient来电,因为所有HttpClient次来电都会在收到服务器的响应后完成整个流程。一旦可观察流完成或出现错误,生产者就有责任释放资源。有关更多信息,请阅读Insider’s guide into interceptors and HttpClient mechanics in Angular。只有在您要取消请求时才应取消订阅。

  

因为AJAX调用不是流或事件,所以一旦完成它们就完成了...比简单承诺更有优势,看起来更清晰   执行后立即销毁?

AJAX调用不只是一次性事件。例如,您可以使用XHR多个progress events。 Promise只使用一个值进行解析,而HttpClient可以发出多个HTTP事件:

export type HttpEvent<T> =
HttpSentEvent | HttpHeaderResponse | HttpResponse<T>| HttpProgressEvent | HttpUserEvent<T>

答案 1 :(得分:5)

有限的,冷的Observable通常不需要取消订阅。在这方面,他们就像Promises一样工作。假设您在服务中使用Angular的HttpClient,则不需要取消订阅 - 在这种情况下,它就像承诺一样。

首先,要清除一些内容 - 在Promise示例中,您必须通过将Promise分配给this.dataSubscription来管理Promise。在进行调用之后,在HTTP调用之后调用this.dataSubscription.then()任意时间量的任何内容都将收到Promise.resolve()并调用.then()函数。 Promise.resolve()返回的新承诺将在执行后进行清理,但只有在您的课程被销毁后才会清除您的this.dataSubscription承诺。

但是,不将Promise指定为属性更清晰:

public remove(data: IData): void {
  this.dataService
    .delete(data.id)
    .then(() => {
      this.refresh();
    });
}

另外,Promise将在其范围的最后清理,而不是在类的破坏中清理。

可观察者,至少是有限的,像承诺一样的&#39;像这样的人,工作方式大致相同。您不需要管理Subscription返回购买.subscribe()方法,因为它会执行然后被清理,因为它没有被指定为属性:

public remove(data: IData): void {
  this.dataService
    .delete(data.id)
    .subscribe(() => {
      this.refresh();
    });
}

订阅后,它是一个有限的Observable和完成,因此再次调用subscribe将返回一个新的Subscription并重新调用Observable的函数。

无法管理这些订阅确实很乱,通常情况下可以做得更好。

与RXJS的订阅管理的不同之处在于,RXJS可以成为一个非常强大的工具,对于方式非常有用,方式比管理异步AJAX调用更有用。您可以拥有向数百个订阅者发布数据的热Observable,向多个订阅者管理自己的流的主题,永不停止发出的无限Observable,管理状态的高阶Observable以及返回其他Observable等。在这种情况下,取消订阅< em>最佳实践,但老实说,在极端情况下不会导致性能问题。

良好的比较是Observable.fromEvent()属性。就像在removeEventListener之后正确使用addEventListener的最佳做法一样,您应该正确地取消订阅此Observable。但是,就像removeEventListener一样,......它并不是一直都在做,而且通常不会导致今天的平台出现问题。

另外,参考“RxJS合同”&#39;陈述:这里是同一个文档的摘录:

When an Observable issues an OnError or OnComplete notification to its observers, this ends the subscription. Observers do not need to issue an Unsubscribe notification to end subscriptions that are ended by the Observable in this way.

有限观察者在排放后自行完成,不需要取消订阅。

答案 2 :(得分:2)

您无需取消订阅每个ajax电话。但是,你正在失去Observables的核心优势之一 - 能够取消它。

您真的需要考虑代码的作用以及您的标准工作流程。如果删除响应需要很长时间并且用户再次单击它,或者单击它或转到其他页面,会发生什么? 您是否希望刷新仍然发生(因为observable仍会将回调保留在内存中)或者您是否愿意取消它?

最后由您和您的申请决定。通过使用取消订阅,您可以避免计划外的副作用。

在你的情况下,它只是一个刷新,所以这不是什么大不了的事。然后,你会把它留在记忆中,它可能会引起一些副作用。