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

Angular2:从服务中可观察到的http取消订阅,angular,rxjs5,unsubscribe,Angular,Rxjs5,Unsubscribe,在Angular2服务中取消http订阅的最佳实践是什么 目前我这样做,但我不确定这是否是最好的方式 import { Injectable } from "@angular/core"; import { Http } from "@angular/http"; import { Subject } from "rxjs/Subject"; import { ISubscription } from "rxjs/Subscription"; @Injectable() export cla

在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/core”导入{Injectable};
从“@angular/Http”导入{Http};
从“rxjs/Subject”导入{Subject};
从“rxjs/Subscription”导入{ISubscription};
@可注射()
导出类搜索服务{
private_searchSource=新主题();
公共搜索$=此。\u searchSource.asObservable();
构造函数(私有http:http){}
公共搜索(值:字符串){
let sub:ISubscription=this.\u http.get(“/api/search?value=“+value”)
.map(response=>response.json())
.do(数据=>this.\u searchSource.next(数据))
.最后(()=>sub.unsubscribe()).subscribe();
}
}

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

您需要取消订阅observable的原因是为了避免内存泄漏。什么时候会出现内存泄漏?如果某个对象在订阅可观察、事件侦听器、套接字时被垃圾收集

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


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

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

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

我不同意您的回答。 是的,在HttpClient呼叫可观察的情况下,不需要如正确所述取消订阅,但是在其他可观察的情况下,您可能确实需要取消订阅服务

让我们看一个简单的例子:假设我们有一个发送可观测数据的存储,并且在存储中我们有一个
点击器
可观测数据,每当点击鼠标右键时(出于某种奇怪的原因)就会触发
true
假设我们有
MyWeirdService
可以执行以下操作:

class MyWeirdService {
  doSomethingUnthinkableManyTimes() {
    this.store.select('clicker').subscribe(() => {
      console.log("Hey what do you know, I'm leaking");
    });
  }
}
this.store.select('clicker')
在每次调用
doSomethingThinkableManytimes
时返回一个可观察到的信息,即我们向它注册一个新的处理程序,而不清理它,这将导致内存泄漏,并在服务存在的时间内保持(在许多情况下,应用程序的生命周期)

底线是,在上面解释的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. 

您需要理解,服务文件应该仅用于定义http方法,而不是订阅http方法本身。
在服务文件中创建方法,使用依赖项注入在组件中注入该服务,然后使用ngOnDesteoy终止订阅
******这在component.ts文件中*******
//引入新的subject变量以销毁订阅
销毁$:主题=新主题();
构造函数(私有serviceName:yoirService){}//依赖项注入
//无论您在哪里想要取消订阅可观察或订阅
this.serviceName.observeName.pipe(takeUntil(this.destroy$)).subscribe(
//所需代码
);
//使用ngondstroy()杀死它
恩贡德斯特罗(){
this.destroy$.next();
此.destroy$.complete();
}
这样,一旦组件被销毁,您就可以销毁服务。

当可观察对象完成时取消订阅似乎是多余和毫无意义的。@günter-zöchbauer好吧,这不是我的问题,如果它有意义,我的问题是:什么是最佳实践。所以呢?我不认为有什么最佳实践可以解决那些毫无意义的事情:D也许只是——不要这样做。我不应该做什么@günter-zöchbauer也许一个解释会很好,而不是毫无帮助的评论感谢@kwintenp的答案。但正如你在上面看到的,搜索方法的每次调用都会创建一个新的可观察对象,我必须订阅它才能获得数据。我不是必须取消订阅以避免内存泄漏吗?没关系。返回的每个订阅都将自行清理。HTTP服务在其自身之后进行清理。当收到XHR结果时,将调用订阅的complete方法,从而取消订阅本身。但是,可能需要对http服务返回的Observable调用unsubscribe方法。如果我们想取消正在进行的HTTP请求,我们将调用unsubscribe。这会在后台调用abort来完成清理。“该服务将在应用程序的整个生命周期内存在”不是真的。我可以在组件的生命周期内提供服务,这样当组件被破坏时,它就会被破坏……”结论:取消订阅服务是毫无意义的,因为没有内存泄漏的机会。”我认为更准确的说法是,不需要取消订阅angular的http服务创建的观测值。可能存在两个组件共享的服务引用订阅中的某个对象的情况。如果共享服务被垃圾回收(请参阅上面的@MarkusE.comment),您可能会导致内存泄漏。我知道这是一个旧线程,但我想添加这个线程,因为我来这里是想了解如何取消订阅服务中非单例(特别是单例)的观察对象的信息。我坚持使用