简体   繁体   中英

How to cancel a subscription in Angular2

How does one cancel a subscription in Angular2? RxJS seems to have a dispose method, but I can't figure out how to access it. So I have code that has access to an EventEmitter and subscribes to it, like this:

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

How can I use mySubscription to cancel the subscription?

您要取消订阅吗?

mySubscription.unsubscribe();

I thought I put in my two cents too. I use this pattern:

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();
        });
    }
}

EDIT

I read the documentation the other day and found a more recommended pattern:

ReactiveX/RxJS/Subscription

Pros:

It manages the new subscriptions internally and adds some neat checks. Would prefer this method in the feature :).

Cons:

It isn't 100% clear what the code flow is and how subscriptions are affected. Nor is it clear (just from looking at the code) how it deals with closed subscriptions and if all subscriptions are getting closed if unsubscribe is called.

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();
    }
}

EDIT: This does not apply to RxJS 5, which is what angular2 is using.

I would have thought you are looking for the dispose method on Disposable .

the subscribe method returns a Disposable ( link )

I can't seem to find it more explicitly in the docs, but this works ( jsbin ):

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

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

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

Weirdly, unsubscribe seems to be working for you while it's not working for me...

Far too many different explanations of unsubscribe on Observables for ng2, took me ages to find the right answer. Below is a working example (I was trying to throttle 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(); } }

ngOnDestroy(){
   mySubscription.unsubscribe();
}

Prefer unsubscribing rxjs unsubscribe's while destroying the component ie, removing from DOM for avoiding unecessary memory leaks

I prefer personally to use a Subject to close all subscriptions a component might have at the destroy life cycle step which can be achieved this way :

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();
  }
}

The recommended approach is to use RxJS operators such as the takeUntil operator. Below is the code snippet showing how to use it :-

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();
    }
}

You can find a detailed explanation of the topic here

Use

if(mySubscription){
  mySubscription.unsubscribe();
}
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { SomeAPIService } from '../some_file/someAPIService.service.ts

@Component({
  templateUrl: './your_Page.html',
  styleUrls: ['./your_Styles.scss']
})

export class (your class) implements OnInit, OnDestroy {
   // This is a subject variable at it simplest form 
     private unsubscribe$ = new Subject<void>();

     constructor (private someAPIService : SomeAPIService) {}
   
     ngOnit(): void { 
       this.someAPIService.getTODOlist({id:1})
        .pipe(takeUntil(this.unsubscribe$))
         .subscribe((value: SomeVariable) => {
         // What ever value you need is SomeVariable
      },)
    }


     ngOnDestroy(): void {
    // clears all, page subscriptions 
      this.unsubscribe$.next();
      this.unsubscribe$.complete();
     }
`}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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