Angular2:取消订阅服务中的http observable

NCC*_*9-M 32 unsubscribe rxjs5 angular

从http订阅中取消订阅Angular2服务的最佳做法是什么?

目前我这样做,但我不确定这是否是最好的方式.

import { Injectable } from "@angular/core";
import { Http } from "@angular/http";

import { Subject } from "rxjs/Subject";
import { ISubscription } from "rxjs/Subscription";

@Injectable()
export class SearchService {
    private _searchSource = new Subject<any>();

    public search$ = this._searchSource.asObservable();

    constructor(private _http: Http) {}

    public search(value: string) {
        let sub: ISubscription = this._http.get("/api/search?value=" + value)
            .map(response => <any>response.json())
            .do(data => this._searchSource.next(data))
            .finally(() => sub.unsubscribe()).subscribe();
    }

}
Run Code Online (Sandbox Code Playgroud)

Kwi*_*enP 80

Angular中的服务是单身人士.这意味着该服务将在您的应用程序的整个生命周期中存在.

您需要取消订阅observable的原因是为了避免内存泄漏.你什么时候得到内存泄漏?如果某些内容已经被垃圾收集,它仍然订阅了一个observable,事件监听器,套接字,......

由于Angular服务永远不会被破坏,除非您的整个应用程序被破坏,否则没有真正的理由取消订阅它.只要您的应用程序执行,observable将完成或错误或继续运行.

结论:取消订阅服务是没有意义的,因为没有内存泄漏的可能性.

  • "服务将在您的应用程序的整个生命周期中存在"并非如此.我可以仅为组件的生命周期提供服务,以便在组件被销毁时被销毁... (26认同)
  • "结论:取消订阅服务是没有意义的,因为没有内存泄漏的可能性." 我认为更准确地说,不需要取消订阅由angular的http服务创建的可观察对象.可能存在两个组件共享的服务引用订阅内的某个对象的情况.如果该共享服务被垃圾收集(请参阅上面的@MarkusE.评论),您最终可能会发生内存泄漏. (9认同)
  • 那没问题。每个返回的订阅都会自行清理。HTTP 服务会自行清理。当收到 XHR 结果时,将调用订阅的 Complete 方法,从而取消订阅本身。但是,可能存在对 http 服务返回的 Observable 调用 unsubscribe 方法的情况。如果我们想取消正在进行的 HTTP 请求,我们会调用 unsubscribe。这会在幕后调用中止来完成清理。 (2认同)

Kfi*_*rez 13

我不同意KwintenP 的回答。是的,如果可观察到 HttpClient 调用,则无需像Vladimir正确提到的那样取消订阅,但是在其他可观察中,您可能肯定需要取消订阅服务。

让我们看一个简单的例子:假设我们有一个发送 observable 的商店,并且在商店中我们有一个clickerobservable,true只要点击鼠标右键(出于某种奇怪的原因)就会触发 observable并假设我们MyWeirdService执行以下操作:

class MyWeirdService {
  doSomethingUnthinkableManyTimes() {
    this.store.select('clicker').subscribe(() => {
      console.log("Hey what do you know, I'm leaking");
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

this.store.select('clicker')返回一个 observable,我们在每次调用时向它注册一个新的处理程序doSomethingUnthinkableManyTimes而不清理它,导致内存泄漏,只要服务在那里就会一直存在(在许多情况下是应用程序生命周期)

最重要的是,在上面的 Http 情况下,您不需要取消订阅,因为Vladimir解释得很好,但在其他情况下您可能需要它。

-------------- 版------------

要在我的示例中解决该问题,只需添加take(1)它,它会在每个流被触发后自动取消订阅:

class MyWeirdService {
  doSomethingUnthinkableManyTimes() {
    this.store.select('clicker')
     .pipe(take(1))
     .subscribe(() => {
      console.log("What a relief, I'm not leaking anymore");
     });
  }
}
Run Code Online (Sandbox Code Playgroud)


Vla*_*kov 7

您不需要取消订阅由 observable 创建的HttpHttpClient因为它是有限的 observable(值将只发出一次并被complete调用)。

但是,您可以取消订阅创建的 observableHttpClient取消请求。这意味着您不再对请求返回的数据感兴趣。