繁体   English   中英

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

[英]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 服务永远不会被销毁,除非您的整个应用程序被销毁,否则没有真正的理由取消订阅它。 observable 要么完成,要么出错,要么继续运行,只要你的应用程序这样做。

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

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

让我们看一个简单的例子:假设我们有一个发送 observable 的商店,并且在商店中我们有一个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')返回一个 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");
     });
  }
}

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

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

你可以这样做:

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. 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM