Как отменить подписку в Angular2


Как можно отменить подписку в Angular2? RxJS, похоже, имеет метод dispose, но я не могу понять, как получить к нему доступ. Поэтому у меня есть код, который имеет доступ к EventEmitter и подписывается на него, например:

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

Как я могу использовать mySubscription отменить подписку?

8 66

8 ответов:

вы хотите отписаться?

mySubscription.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 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

Я прочитал документацию на днях и нашел более рекомендуемый шаблон:

ReactiveX/RxJS / Subscription

плюсы:

Он управляет новыми подписками внутри и добавляет некоторые аккуратные проверки. Предпочел бы этот метод в функции :).

плюсы:

это не 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();
    }
}

EDIT: Это не относится к RxJS 5, который является то, что angular2 использует.

Я бы подумал, что вы ищете метод Dispose одноразовая.

метод subscribe возвращает одноразовый (ссылке)

Я не могу найти его более явно в документах, но это работает (jsbin):

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

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

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

странно, отписаться, кажется, работает для вас пока это не работает для меня...

слишком много разных объяснений отказа от подписки на наблюдаемые для ng2, потребовалось много времени, чтобы найти правильный ответ. Ниже приведен рабочий пример (я пытался дросселировать 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();
}

предпочитаю отказаться от подписки rxjs отписаться при уничтожении компонента, т. е. удаление из DOM для предотвращения ненужных утечек памяти

Я предпочитаю лично использовать тему для закрытия всех подписок, которые компонент может иметь на этапе жизненного цикла destroy, который может быть достигнут таким образом:

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

использовать

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

рекомендуется использовать операторы 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();
    }
}

вы можете найти подробное объяснение темы здесь