web-dev-qa-db-fra.com

Comment annuler un abonnement dans Angular2

Comment annuler un abonnement dans Angular2? RxJS semble avoir une méthode de disposition, mais je n'arrive pas à comprendre comment y accéder. J'ai donc un code qui a accès à un EventEmitter et qui s'y abonne, comme ceci:

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

Comment utiliser mySubscription pour annuler l'abonnement?

74
Michael Oryl

Souhaitez-vous vous désabonner?

mySubscription.unsubscribe();
111
kendaleiv

Je pensais avoir mis mes deux cents aussi. J'utilise ce motif:

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

J'ai lu la documentation l'autre jour et j'ai trouvé un modèle plus recommandé:

ReactiveX/RxJS/Abonnement

Avantages:

Il gère les nouveaux abonnements en interne et ajoute des vérifications soignées. Préférerait cette méthode dans la fonctionnalité :).

Les inconvénients:

Le flux de code et les abonnements ne sont pas clairement définis à 100%. La manière dont il traite les abonnements fermés et si tous les abonnements sont fermés si la désinscription est appelée n'est pas claire non plus (juste en regardant le code).

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

EDIT: Ceci ne s'applique pas à RxJS 5, qui est ce que angular2 utilise.

J'aurais pensé que vous cherchiez la méthode de disposition sur Disposable .

la méthode subscribe renvoie un jetable ( lien )

Je n'arrive pas à le trouver plus explicitement dans la documentation, mais cela fonctionne ( jsbin ):

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

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

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

Bizarrement, la désinscription semble fonctionner pour vous alors que ça ne fonctionne pas pour moi ...

9
Niklas Fasching

Beaucoup trop d’explications différentes de la désinscription sur Observables for ng2 m’ont pris beaucoup de temps pour trouver la bonne réponse. Vous trouverez ci-dessous un exemple de travail (j’essayais d’étrangler la souris).

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();
  }
  
}
4
Joe Keene
ngOnDestroy(){
   mySubscription.unsubscribe();
}

Préférer la désinscription de la désinscription de rxjs lors de la destruction du composant, c'est-à-dire la suppression de DOM pour éviter les fuites de mémoire inutiles

2
Prithvi Uppalapati

Je préfère utiliser personnellement un sujet pour fermer tous les abonnements qu'un composant peut avoir à l'étape du cycle de vie de la destruction, ce qui peut être réalisé de la manière suivante:

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
Jahrenski

L'approche recommandée consiste à utiliser des opérateurs RxJS tels que l'opérateur takeUntil . Ci-dessous l'extrait de code montrant comment l'utiliser: -

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

Vous pouvez trouver une explication détaillée du sujet ici

1

Utilisation

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