Angular2에서 구독을 취소하는 방법


81

Angular2에서 구독을 어떻게 취소합니까? RxJS에 처리 방법이있는 것 같지만 액세스 방법을 알 수 없습니다. 그래서 다음과 같이 EventEmitter에 대한 액세스 권한이 있고 구독하는 코드가 있습니다.

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

어떻게 사용할 수있는 mySubscription구독을 취소하려면?


2
참고-Reactive 작업을 수행하려면 Angular의 EventEmitter 대신 Subject를 사용하십시오. Subject의 수퍼 클래스로 유지된다는 보장은 없습니다. @Output 이벤트에만 EventEmitter를 사용하십시오.
robwormald

답변:


121

구독을 취소 하시겠습니까?

mySubscription.unsubscribe();

4
맙소사. 나는 이미 그것을 시도했다고 맹세했다. 나는 RxJS 소스를 살펴 보았고 그것이 그랬던 것처럼 보였다. 문제를 일으키는 다른 오류가 있었음에 틀림 없습니다. 감사.
Michael Oryl 2015

1
이것은 잘 작동하지만 mySubscriptionTypeScript 의 유형이 궁금합니다. mySubscription: any수업 시간에 글을 쓰는 것을 피하고 싶습니다 .
paradite

11
@paradite import { Subscription } from "rxjs";및 구독 취소 if (!mySubscription.closed) { mySubscription.unsubscribe(); }.
Llyle

9
import { Subscription } from 'rxjs/Subscription';패키지 크기 아래로 유지하는 데 도움이됩니다

50

나도 2 센트를 넣었다고 생각했다. 이 패턴을 사용합니다.

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 % 명확하지 않습니다. 종료 된 구독을 처리하는 방법과 구독 취소가 호출되면 모든 구독이 종료되는지 여부도 코드를 보면 명확하지 않습니다.

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

편집 : 이것은 angular2가 사용하는 RxJS 5에는 적용되지 않습니다.

Disposable 에서 dispose 메서드를 찾고 있다고 생각했을 것 입니다.

subscribe 메서드는 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 dec.

예, Angular 2는 RxJS 5를 사용합니다.
Michael Oryl 2015

1
그게 다야. 여기 에서 찾을 수 있습니다 . ES7 Observable Spec
Niklas Fasching

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

권장되는 접근 방식은 takeUntil 연산자와 같은 RxJS 연산자를 사용하는 입니다. 다음은 사용 방법을 보여주는 코드 스 니펫입니다.

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

-1
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();
     }
`}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.