如何以角度2取消订阅多个订阅者

时间:2016-06-08 07:11:21

标签: javascript angular rxjs

我有另一个组件的shareService和subscribe:

import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription }   from 'rxjs/Subscription';
@Component({
  selector: 'my-astronaut',
  template: `
    <p>
      {{astronaut}}: <strong>{{mission}}</strong>
      <button
        (click)="confirm()"
        [disabled]="!announced || confirmed">
        Confirm
      </button>
    </p>
  `
})
export class AstronautComponent implements OnDestroy{
  @Input() astronaut: string;
  mission = "<no mission announced>";
  confirmed = false;
  announced = false;
  subscription:Subscription;

  constructor(private missionService: MissionService) {
    this.subscription = missionService.missionAnnounced$.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    })




  }
  confirm() {
    this.confirmed = true;
    this.missionService.confirmMission(this.astronaut);
  }
  ngOnDestroy(){
    // prevent memory leak when component destroyed
    this.subscription.unsubscribe();

  }
}

我想知道我的constructor中是否有2个订阅者,如何取消订阅ngDestroy中的两个订阅者? 我应该使用subscription2:Subscription;?和ngDestroy this.subscription2.unsubscribe();? 这是真的吗?

3 个答案:

答案 0 :(得分:29)

您可以在数组ngOnDestroy()中收集要立即取消订阅的订阅

export class AstronautComponent implements OnDestroy{
  @Input() astronaut: string;
  mission = "<no mission announced>";
  confirmed = false;
  announced = false;
  subscriptions:Subscription[] = [];

  constructor(private missionService: MissionService) {
    this.subscriptions.push(missionService.missionAnnounced$.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    }));

    this.subscriptions.push(fooService.fooObservable$.subscribe(
      ...
    }));
  }

  confirm() {
    this.confirmed = true;
    this.missionService.confirmMission(this.astronaut);
  }

  ngOnDestroy(){
    // prevent memory leak when component destroyed
    this.subscriptions.forEach(s => s.unsubscribe());
  }
}

答案 1 :(得分:16)

Subscription可以保留子订阅并安全地取消订阅所有订阅。此方法处理可能的错误(例如,如果任何子订阅为null)。此外,如果在调用ngOnDestroy后添加了任何订阅,则会立即取消订阅。

应注意Subscription.add()会返回添加的订阅。因此,将add()subManager.add(sub1).add(sub2)相关联会将sub2添加到sub1。如果sub1在较早时间取消订阅,则会出现问题,因为它也会取消订阅sub2

import { OnDestroy } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";

export class MyComponent implements OnDestroy {
    ob1: Observable<number>;
    ob2: Observable<number>;
    subManager = new Subscription();

    constructor() {
        this.ob1 = Observable.interval(1000);
        this.ob2 = Observable.interval(2000);

        let sub1 = this.ob1.subscribe(val => console.log(val));
        let sub2 = this.ob2.subscribe(val => console.log(val));

        // DO NOT CHAIN add() - SEE ABOVE
        this.subManager.add(sub1);
        this.subManager.add(sub2);
    }

    ngOnDestroy() {
        this.subManager.unsubscribe();
    }
}

来自documentation

  

此外,订阅可以通过add()组合在一起   方法,它将子订阅附加到当前   订阅。当订阅取消订阅时,其所有子订阅   (及其孙子女)也将取消订阅。

     

...

     

如果此订阅已处于关闭状态,则通过撕裂   下行逻辑将立即执行。

答案 2 :(得分:0)

我认为,更优雅,更通用(与您有多少订阅无关)是使用rxjs包中的takeUntil运算符。

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

export class MyComponent implements OnDestroy {

    ob1: any;
    ob2: any;

    private _endSubs: Subject<any> = new Subject();
    private endSubs$ = this._endSubs.asObservable();

    constructor() {
        this.ob1 = Observable.interval(1000);
        this.ob2 = Observable.interval(2000);

        let sub1 = this.ob1.pipe(takeUntil(this.endSubs$)).subscribe(val => console.log(val));
        let sub2 = this.ob2.pipe(takeUntil(this.endSubs$)).subscribe(val => console.log(val));

        .... (more subscriptions here)
    }

    ngOnDestroy() {
        this._endSubs.next();
    }
}