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

时间:2016-11-29 08:56:43

标签: angular rxjs5 unsubscribe

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

}

4 个答案:

答案 0 :(得分:60)

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

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

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

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

答案 1 :(得分:2)

我不同意KwintenP的回答。 是的,在可观察到HttpClient调用的情况下,无需取消订阅Vladimir,但是在其他可观察对象中,您肯定需要取消订阅服务。

让我们看一个简单的例子:假设我们有一个商店发送观察值,并且在商店中,有foreach ($results as $row) { $rows[] = [ $row->getId(), ($user = $row->getUser()) ? $user->getFullName() : null, ($category = $row->getCategory()) ? $category->getName() : null, ]; } 个可观察对象,只要单击鼠标右键,它就会触发clicker(出于某些奇怪的原因) ) 并假设我们有true执行以下操作:

MyWeirdService

class MyWeirdService { doSomethingUnthinkableManyTimes() { this.store.select('clicker').subscribe(() => { console.log("Hey what do you know, I'm leaking"); }); } } 返回一个可观察到的结果,我们在每次对this.store.select('clicker')的调用上都向其注册了一个新的处理程序,而没有清除它,导致内存泄漏将一直存在,直到服务存在为止(许多应用程序的生命周期例)

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

答案 2 :(得分:0)

您无需取消订阅HttpHttpClient创建的可观察项,因为它是有限的可观察项(值将仅发出一次,并且将被调用complete)。

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

答案 3 :(得分:0)

你可以这样做:

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.