Angular2:取消订阅服务中可观察到的http

Angular2: Unsubscribe from http observable in Service

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

目前我正在这样做,但我不确定这是否是最好的方法。

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();
    }

}

Angular 中的服务是单例。这意味着该服务将在您的应用程序的整个生命周期内存在。

您需要取消订阅 observable 的原因是为了避免内存泄漏。什么时候发生内存泄漏?如果某些东西在它仍然订阅了一个可观察的、事件监听器、套接字时被垃圾收集了,...

由于 Angular 服务永远不会被销毁,除非您的整个应用程序都被销毁,否则没有真正的理由取消订阅。只要您的应用程序运行,可观察对象就会完成或出错或继续运行。

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

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

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

我不同意 的回答。 是的,在可观察到 HttpClient 调用的情况下,不需要取消订阅,正如 正确提到的那样,但是在其他可观察到的情况下,您可能肯定需要取消订阅服务。

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

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

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

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

------------版本------------

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

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

你可以这样做:

You need to understand that the service file should be used to just define the http methods and not subscribe there itself. 
Create the method in the service file, use Dependency injection to inject that service in the component and then use ngOnDesteoy to kill the subscription 

****** this is in your component.ts file *******
// introduce a new subject variable to destroy the subscription
destroy$: Subject<any> = new Subject();

constructor(private serviceName: yoirService){} // Dependency injection 

// wherever you want to unsubsribe an observable or a subscription
this.serviceName.observableName.pipe(takeUntil(this.destroy$)).subscribe(
    // required code 
);

//  use ngOnDestroy() to kill it
ngOnDestroy() {
   this.destroy$.next();
   this.destroy$.complete();
}

This way you'll destroy the service once the component is destroyed.