Angular observables - 如果没有订阅,我是否需要取消订阅? [英] Angular observables - Do I need unsubscribe if no subscription?

查看:17
本文介绍了Angular observables - 如果没有订阅,我是否需要取消订阅?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用最新的 angular 8,并且对 observables 的概念还不熟悉.问题是如果我直接调用一个 observable 而不是将它应用到订阅变量,我是否还需要取消订阅.以下是我想知道是否需要取消订阅的情况?非常感谢提前

I am using latest angular 8 and am new to the concept of observables. Question I have if I am directly calling an observable and not apply it to a subscription variable, do I still need to unsubscribe. Below are the scenarios I would like to know if I need to unsubscribe on? Many thanks in advance

场景 1 - 从组件调用 httpService:

Scenario 1 - Calling a httpService from a component:

Service - httpService

     getContactsHttp(){
         let headers: any = new HttpHeaders(this.authService.getHeadersClient());
         return this.httpClient.get('/contacts', {headers: headers})
          .pipe(timeout(this.authService.getTimeoutLimit('normal')));
        }

Component - Calling getContactsHttp and sorting response

getContacts() {
 this.httpService.getContactsHttp().subscribe((data:any[])=>{
  this.records = this.sortData(data)
 })
}

场景 2 - 在组件中订阅的 observable

Scenario 2 - on an observable susbcribed in a component

contacts$: new Subject<any[]>;

ngOnInit() {
  this.getContacts();
  this.contacts$.subscribe((data:any[])=>{
    this.records = this.sortData(data);
  })
}

getContacts() {
    this.httpService.getContactsHttp().subscribe((data:ContactSearch[])=>{      
      this.contacts$.next(data);
    })
  }

服务 - httpService

Service - httpService

     getContactsHttp(){
         let headers: any = new HttpHeaders(this.authService.getHeadersClient());
         return this.httpClient.get('/contacts', {headers: headers})
          .pipe(timeout(this.authService.getTimeoutLimit('normal')));
        }

推荐答案

1) 一般情况下,直接调用 http 调用时不需要取消订阅.即使组件 get 被销毁,销毁后订阅完成的开销也是微不足道的.如果快速切换组件,您需要在此处取消订阅.取消订阅也会取消 http 请求,因此如果需要,请取消订阅.

1) Generally, you don't need to unsubscribe when calling an http call directly. Even if the component get's destroyed, the overhead with the subscription finishing after the destruction is insignificant. You'd need to unsubscribe here if switching your components rapidly. Also unsubscribing cancels the http request, so if that's desired, then unsubscribe.

取消订阅不会造成任何伤害.如果您不确定,请随时退订.

Unsubscribing does not do any harm. If you're not sure, always unsubscribe.

2) 当您订阅一个在您的组件被销毁时未完成的 observable 时,您确实需要取消订阅.否则这会导致内存(和性能)泄漏.由于 observable 本身持有对订阅的引用,而订阅持有对组件的引用,因此该组件永远不会从内存中清除,订阅中描述的操作将一直运行,直到 observable 完成,在您的情况下永远不会.您的组件的每个实例都会发生这种情况.

2) You do need to unsubscribe when subscribing to an observable that does not complete when your compoment gets destroyed. Otherwise this would cause a memory (and performance) leak. Because the observable itself holds a reference to the subscription and the subscription holds the reference to the component, the component will never get cleared from the memory and the action described in the subscription will be running until the observable completes, which in your case is never. That will happend for every instance of your component.

我将分享两个简化退订负担的流行选项.扩展@amanagg1204 答案,您可以创建一个基础组件,您可以从中扩展所有未来的组件.您可以在其中使用自定义运算符.这样做有一个缺点——如果你需要在你的组件中使用 ngOnDestroy,你总是必须调用 super.ngOnDestroy().

I'll share two popular options on simplifying the burden of unsubscribing. Expanding on the @amanagg1204 answer, you could create a base component from which you'd extend all of your future components. You can have a custom operator in it. There is one downside to that - you always have to call super.ngOnDestroy() if you need to use ngOnDestroy in your component.

import { OnDestroy } from "@angular/core";
import { Subject, MonotypeOperatorFunction } from "rxjs";
import { takeUntil } from "rxjs/operators";

export abstract class UnsubscribeComponent implements OnDestroy {
  protected destroyed$: Subject<void> = new Subject();

  ngOnDestroy(): void {
    this.destroyed$.next();
    this.destroyed$.complete();
  }

  takeUntilDestroyed<T>(): MonoTypeOperatorFunction<T> {
      return takeUntil(this.destroyed$);
  }
}

export class Component extends UnsubscribeComponent {
   ngOnInit() {
      this.contacts$.pipe(
              this.takeUntilDestroyed(),
          ).subscribe((data:any[])=>{
          this.records = this.sortData(data);
      });
   }

  // WARNING - if you declare your ngOnDestroy in the component
  ngOnDestroy() {
     // DO NOT FORGET to call this
     super.ngOnDestroy();
     doYourStuff();
  }

}

其他选项(我的首选)不是拥有父抽象类(尽管也可以这样实现),而是使用名为 subsink (npm i subsink --save)

Other option (my prefered) is not to have a parent abstract class (although it could also be implemented like that), but to use an utility called subsink (npm i subsink --save)

import { SubSink } from 'subsink';

export class SampleComponent implements OnInit, OnDestroy {
  private subs = new SubSink();

  ngOnInit(): void {
    // Just put it into sink.
    this.subs.sink = this.contacts$.subscribe((data:any[])=>{
      this.records = this.sortData(data);
    });
    // call repeatedly
    this.subs.sink = this.otherService$.subscribe((data:any[])=>{
      this.things = this.sortData(data);
    });
  }

  ngOnDestroy(): void {
    // this will unsubscribe all
    this.subs.unsubscribe();
  }
}

这篇关于Angular observables - 如果没有订阅,我是否需要取消订阅?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆