Angular2でサブスクリプションをキャンセルする方法


81

Angular2でサブスクリプションをキャンセルするにはどうすればよいですか?RxJSにはdisposeメソッドがあるようですが、アクセス方法がわかりません。したがって、次のように、EventEmitterにアクセスしてサブスクライブするコードがあります。

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

mySubscriptionサブスクリプションをキャンセルするにはどうすればよいですか?


2
参考までに-リアクティブなことを行う場合は、AngularのEventEmitterではなくSubjectを使用してください-Subjectのスーパークラスのままであるという保証はありません。EventEmitterは@Outputイベントにのみ使用してください。
robwormald 2015

回答:


121

退会をお考えですか?

mySubscription.unsubscribe();

4
グッドロード。私はすでにそれを試したことを誓った。私はRxJSソースを調べましたが、それがそれであるように見えました。問題を引き起こしている別のエラーがあったに違いありません。ありがとう。
Michael Oryl 2015

1
これはうまく機能しますがmySubscription、TypeScriptのタイプが何であるか知りたいです。mySubscription: anyクラスで書くのは避けたいです。
寄生虫2016年

11
@paraditeimport { Subscription } from "rxjs";およびサブスクリプション解除用if (!mySubscription.closed) { mySubscription.unsubscribe(); }
llyle 2016

9
import { Subscription } from 'rxjs/Subscription';パッケージサイズを抑えるのに役立ちます
paul 2017年

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 / Subscription

長所:

新しいサブスクリプションを内部で管理し、いくつかのきちんとしたチェックを追加します。機能でこの方法を好むでしょう:)。

短所:

コードフローとは何か、サブスクリプションがどのように影響を受けるかは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 2017

1
「魔法」はありません-設計によるものです:「サブスクリプションをまとめることもできるので、1つのサブスクリプションのunsubscribe()を呼び出すと、複数のサブスクリプションのサブスクライブを解除できます。これを行うには、1つのサブスクリプションを別のサブスクリプションに「追加」します: " github。 com / ReactiveX / rxjs / blob / master / doc /
subset.md

あなたが興味を持つかもしれないもう一つの明確なアプローチがあります。takeWhile演算子を使う。ここで説明するアプローチ:brianflove.com/2016/12/11/anguar-2-unsubscribe-observables
vdshb

takeUntilを使用している代替ソリューションを確認してください。さまざまなオプションを考慮して、豊富で興味深い議論があります。
Alex Klaus

8

編集:これは、angular2が使用しているRxJS5には適用されません。

Disposableでdisposeメソッドを探していると思います。

subscribeメソッドはDisposable(リンク)を返します

ドキュメントでそれをより明確に見つけることはできないようですが、これは機能します(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 Observable Spec
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

私は個人的にサブジェクトを使用して、コンポーネントがライフサイクルの破棄ステップで持つ可能性のあるすべてのサブスクリプションを閉じることを好みます。これは次の方法で実現できます。

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 BandhuBhandary20年

1

使用する

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

1
実際にはif (!mySubscription.closed) { mySubscription.unsubscribe(); }
Llyle 2016

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