LoginSignup
37
29

More than 5 years have passed since last update.

angularでObservable(ストリーム)のsubscribeを停止する方法

Last updated at Posted at 2017-10-26

angularではRxJSでストリームを扱うことが多い。そうした中で画面遷移が絡む場合、画面遷移した後でも、前の画面で使用していたsubscribeが生き続けるといった問題が発生する。

ということで、必要に応じて画面遷移した際に、unsubscribeしてあげる必要がある。

OnDestroy時にunsubscribeする方法

unsubscribeする方法として、まずコンポーネントをOnDestroyする際に、unsubscribeする方法がある。

RxJSのSubscription#unsubscribeを使う。
http://reactivex.io/rxjs/class/es6/Subscription.js~Subscription.html

実装すると以下のようになる。

...

// 必要に応じて以下をインポートする
import { Subscription } from 'rxjs';

...

export class App implements OnInit, OnDestroy {
  eventStream$: Observable<EventStream>
  subscription: Subscription;

  ngOnInit() {
    this.subscription = this.eventStream$.subscribe(...);
  }

  ngOnDestroy() {
    // コンポーネントを破棄する時にunsubscribeする
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

subscribeするストリームが複数ある場合は、subscriptionを配列にしても良い。

...

export class App implements OnInit, OnDestroy {
  eventStream1$: Observable<EventStream>
  eventStream2$: Observable<EventStream>
  subscriptions: Subscription[] = [];

  ngOnInit() {
    this.subscriptions.push(this.eventStream1$.subscribe(...));
    this.subscriptions.push(this.eventStream2$.subscribe(...));
  }

  ngOnDestroy() {
    if (this.subscriptions) {
      this.subscriptions.forEach(sub => sub.unsubscribe());
    }
  }
}

URLを基準にイベントをフィルタリングする方法

こちらは、unsubscribeする代わりに、特定のURLの時だけsubscribeする方法。

RxJSのfilterオペレータを使う。
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-filter

実装すると以下のようになる。

...

// 必要に応じて以下をインポートする
import { Router } from '@angular/router';
import 'rxjs/add/operator/filter';

...

export class App implements OnInit {
  eventStream$: Observable<EventStream>

  constructor(
    private router: Router,
  ) { }

  ngOnInit() {
    this.eventStream$
      // URLが'/app'の時だけsubscribeする
      .filter((eventStream: EventStream) => this.router.url === '/app')
      .subscribe(...);
  }
}

subscribeするのは1回だけで良い場合

unsubscribeで停止しても良いが、RxJSのtakeオペレータを使っても良い。
http://reactivex.io/documentation/operators/take.html

実装すると以下のようになる。

...

// 必要に応じて以下をインポートする
import 'rxjs/add/operator/take';

...

export class App implements OnInit, OnDestroy {
  eventStream$: Observable<EventStream>

  ngOnInit() {
    this.eventStream$.take(1).subscribe(...);
  }
}

まとめ

状況に応じて使い分ける。ブラウザの戻る、進むによってsubscribeが重複したりするので、その辺りは十分に注意する。

37
29
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
29