如何在Angular2中取消订阅


80

如何在Angular2中取消订阅?RxJS似乎有一个dispose方法,但是我不知道如何访问它。所以我有访问EventEmitter并订阅它的代码,如下所示:

var mySubscription = someEventEmitter.subscribe(
    (val) => {
        console.log('Received:', val);
    },
    (err) => {
        console.log('Received error:', err);
    },
    () => {
        console.log('Completed');
    }
);

如何使用mySubscription取消订阅?


2
仅供参考-如果您要进行响应式操作,请使用Subject,而不是Angular的EventEmitter-无法保证它将仍然是Subject的超类。仅将EventEmitter用于@Output事件。
robwormald

Answers:


118

您要取消订阅吗?

mySubscription.unsubscribe();

4
好主啊 我发誓我已经尝试过了。我看了看RxJS的源代码,事实似乎就是如此。我一定有其他错误导致我遇到问题。谢谢。
Michael Oryl

1
这很好用,但是我很好奇mySubscriptionTypeScript的类型。我想避免mySubscription: any在课堂上写作。
天堂

11
@paraditeimport { Subscription } from "rxjs";并取消订阅if (!mySubscription.closed) { mySubscription.unsubscribe(); }
Llyle '16

9
import { Subscription } from 'rxjs/Subscription';将有助于减小包裹尺寸
paul

50

我以为我也投入了两分钱。我使用这种模式:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

@Component({
    selector: 'my-component',
    templateUrl: 'my.component.html'
})
export class MyComponent implements OnInit, OnDestroy {

    private subscriptions: Array<Subscription> = [];

    public ngOnInit(): void {
        this.subscriptions.push(this.someService.change.subscribe(() => {
            [...]
        }));

        this.subscriptions.push(this.someOtherService.select.subscribe(() => {
            [...]
        }));
    }

    public ngOnDestroy(): void {
        this.subscriptions.forEach((subscription: Subscription) => {
            subscription.unsubscribe();
        });
    }
}

编辑

前几天,我阅读了文档,发现了一个更推荐的模式:

ReactiveX / RxJS /订阅

优点:

它在内部管理新的订阅并添加一些简洁的检查。在功能中会首选此方法:)。

缺点:

目前尚不清楚100%是什么代码流以及如何影响订阅。也不清楚(仅通过查看代码)它如何处理封闭的订阅,如果调用了unsubscribe,所有订阅是否都将关闭。

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

@Component({
    selector: 'my-component',
    templateUrl: 'my.component.html'
})
export class MyComponent implements OnInit, OnDestroy {

    private subscription: Subscription = new Subscription();

    public ngOnInit(): void {
        this.subscription.add(this.someService.change.subscribe(() => {
            [...]
        }));

        this.subscription.add(this.someOtherService.select.subscribe(() => {
            [...]
        }));
    }

    public ngOnDestroy(): void {
        /*
         * magic kicks in here: All subscriptions which were added
         * with "subscription.add" are canceled too!
         */
        this.subscription.unsubscribe();
    }
}

2
我也使用它,它可以很好地扩展您在组件中拥有的更多订阅。
weltschmerz

1
没有“魔术”-这是设计使然:“订阅也可以放在一起,以便对一个订阅的unsubscribe()的调用可以取消订阅多个订阅。您可以通过将一个订阅“添加”到另一个订阅中来实现:github。 com / ReactiveX / rxjs / blob / master / doc / subscription.md
Meetai.com

您可能会对另外一种清晰的方法感兴趣。使用takeWhile运算符。这里描述的方法:brianflove.com/2016/12/11/anguar-2-unsubscribe-observables
vdshb

签出替代解决方案,它正在使用takeUntil。考虑到不同的选择,这里有一个有趣的讨论。
亚历克斯·克劳斯

8

编辑:这不适用于RxJS 5,这是angular2正在使用的。

我以为您正在寻找Disposable上的dispose方法。

subscription方法返回一个Disposable(link

我似乎无法在文档中更明确地找到它,但这可行jsbin):

var observable = Rx.Observable.interval(100);

var subscription = observable.subscribe(function(value) {
   console.log(value);
});

setTimeout(function() {
  subscription.dispose();           
}, 1000)

奇怪的是,退订似乎对您有用,而对我不起作用...


您可能使用了不同的版本。Angular2在Rxjs5上不是吗?
user3743222 2015年

是的,角2个使用RxJS 5
迈克尔Oryl

1
而已。可以在这里找到。进行了更改,以符合ES7可观察规范
Niklas Fasching 2015年

4

取消订阅ng2的Observables的太多不同解释,花了我很长时间才能找到正确的答案。下面是一个有效的示例(我试图限制mousemove的移动)。

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

@Injectable()
export class MyClass implements OnDestroy {
  
  mouseSubscription: Subscription; //Set a variable for your subscription
  
  myFunct() {
    // I'm trying to throttle mousemove
    const eachSecond$ = Observable.timer(0, 1000);
    const mouseMove$ = Observable.fromEvent<MouseEvent>(document, 'mousemove');
    const mouseMoveEachSecond$ = mouseMove$.sample(eachSecond$);
    
    this.mouseSubscription = mouseMoveEachSecond$.subscribe(() => this.doSomethingElse());
  }

  doSomethingElse() {
    console.log("mouse moved");
  }
  
  stopNow() {
    this.mouseSubscription.unsubscribe();
  }
  
  ngOnDestroy() {
    this.mouseSubscription.unsubscribe();
  }
  
}


2
ngOnDestroy(){
   mySubscription.unsubscribe();
}

在销毁组件的同时,最好选择退订rxjs的退订,即从DOM中删除以避免不必要的内存泄漏


2

我个人更喜欢使用Subject来关闭组件在销毁生命周期步骤中可能拥有的所有订阅,可以通过以下方式实现:

import { Component} from '@angular/core';
import { Subject } from "rxjs/Rx";

@Component({
  selector:    'some-class-app',
  templateUrl: './someClass.component.html',
  providers:   []
})

export class SomeClass {  

  private ngUnsubscribe: Subject<void> = new Subject<void>(); //This subject will tell every subscriptions to stop when the component is destroyed.

  //**********
  constructor() {}

  ngOnInit() {

    this.http.post( "SomeUrl.com", {}, null ).map( response => {

      console.log( "Yay." );

    }).takeUntil( this.ngUnsubscribe ).subscribe(); //This is where you tell the subscription to stop whenever the component will be destroyed.
  }

  ngOnDestroy() {

    //This is where we close any active subscription.
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }
}

2

推荐的方法是使用RxJS运算符,例如takeUntil运算符。下面是显示如何使用它的代码片段:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { interval, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
})
export class AppComponent implements OnInit, OnDestroy {
    private ngUnsubscribe = new Subject();

    constructor() { }

    ngOnInit() {
        var observable1 = interval(1000);
        var observable2 = interval(2000);

        observable1.pipe(takeUntil(this.ngUnsubscribe)).subscribe(x => console.log('observable1: ' + x));
        observable2.pipe(takeUntil(this.ngUnsubscribe)).subscribe(x => console.log('observable2: ' + x));
    }

    ngOnDestroy() {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();
    }
}

您可以在此处找到有关该主题的详细说明


为什么我们需要调用ngUnsubscribe.next(); 在ngOnDestroy()方法中?
Biswa Bandhu Bhandary

1

使用

if(mySubscription){
  mySubscription.unsubscribe();
}

1
其实应该是if (!mySubscription.closed) { mySubscription.unsubscribe(); }
Llyle '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.