6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RxJS入門|SubjectとSubscription編

Last updated at Posted at 2025-12-26

はじめに

前回の記事では、RxJSの基本となる Observable / Observer / Operator について解説しました。

今回はその続編として、Angular + RxJS を使ううえで必ず出てくるSubjectSubscriptionを取り上げます。
本記事では、次のポイントを中心に解説します。

  • ObservableとSubjectの役割と使い分け
  • subscribeした購読はどう管理すべきか
  • unsubscribeが必要になる理由とタイミング

それぞれをコード例とあわせて確認しながら、使いどころのイメージを掴んでいきましょう。

Subject/Subscription

今回扱うのは、以下の2つです。

  • Subject:値を流す側(Observable)にも、受け取る側(Observer)にもなれる存在
  • Subscription:ObservableとObserverを結びつける購読情報

Subject

Subjectは値を流す側(Observable)にも、受け取る側(Observer)にもなれる存在です。
つまり、

  • subscribe()されて値を配ることもできる
  • next()を呼んで自分から値を流すこともできる

という特徴を持っています。

Observableとの違い

Observableとは、以下の違いがあります。

Observable Subject
値の流し方 定義された処理に従って流れる 明示的にnext()で流す
値の送信 外部から直接送れない 外部から送れる
複数購読 可能(基本は独立) 同じ値を全購読者に配信

それぞれに違いについてコード例を見ていきましょう

値の流し方の違い

Observable:定義された処理に従って流れる

ts
import { Observable } from 'rxjs';

const number$ = new Observable<number>(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
});

number$.subscribe(num => {
  console.log('番号 受信:', num);
});
出力
番号 受信: 1
番号 受信: 2

Observableでは、「どの値をどの順番で流すか」はObservableを作った時点で定義されています。
受け取る側は、その流れを購読するだけで、値の発生タイミングや内容を外部から変更することができません。

Subject:明示的にnext()で流す

ts
import { Subject } from 'rxjs';

const numberChange$ = new Subject<number>();

numberChange$.subscribe(num => {
  console.log('番号 受信:', num);
});

// 任意のタイミング・任意の処理から明示的に値を流せる
numberChange$.next(1);

出力
番号 受信: 1

Subjectでは、next()を呼んだタイミングで値が流れます。
値を流す処理は Subjectの外側にあり、任意のタイミングで明示的に値を流すことができます。

値の送信の違い

Observable:外部から直接送れない

ts
const number$ = new Observable<number>(subscriber => {
  subscriber.next(1);
});

number$.next(2); //←できない

Observableでは、値を流せるのはObservableの定義内だけです。
受け取る側と、流す側が明確に分かれています。

Subject:外部から値を送れる

ts
const number$ = new Subject<number>();

number$.next(1);
number$.next(2);

Subjectでは、外部の任意の処理から値を送れます。

複数購読時の違い

Observable:購読ごとに独立した流れ

ts
const number$ = new Observable<number>(subscriber => {
  subscriber.next(Math.random());
});

number$.subscribe(num => {
  console.log('処理開始');
  console.log('購読A:', num);
});

number$.subscribe(num => {
  console.log('購読B:', num);
});
出力
処理開始
購読A: 0.33
処理開始
購読B: 0.21

Observableでは、subscribe()ごとに処理が独立して実行されます。

Subject:1つの値を全購読者で共有

ts
const number$ = new Subject<number>();

number$.subscribe(num => {
  console.log('購読A:', num);
});

number$.subscribe(num => {
  console.log('購読B:', num);
});

number$.next(Math.random());
出力
購読A: 0.92
購読B: 0.92

値は1度だけ生成されていますが、購読A、購読Bの両方に同じ値が届いています。

Observable/Subjectの違いによる使い分け

ObservableはAPIレスポンスやフォームの変更値など、すでに存在するデータを加工・購読する用途に向いています。
Subjectはボタンクリックや状態変更などのイベントをトリガーとして扱う用途に向いています。
したがって、

  • Observable流れてくるデータを定義・加工して使う場合
  • Subject自分でnext()を呼んで値を流したい場合

で使い分けると、役割が明確になります。

Subscription

Subscriptionは、subscribe()を呼んだ結果として得られる、
「ObservableとObserver のつながり(購読)」 を表すオブジェクトです。

Subscriptionの基本

Subscriptionは購読を続けるか、解除するかを管理する役割を持ちます。

購読状態の管理が必要な理由

Subjectやイベント・状態監視などのObservableは、明示的に止めない限り動き続けるという特徴があります。
そのため、購読解除をしないと、

  • コンポーネントが破棄された後も処理が残る
  • 意図しないログ出力や処理実行が続く

などの問題が発生します。

では、購読から購読を解除するまでの流れを見ていきましょう。

Subjectを購読する

ts
import { Subject } from 'rxjs';

const statusChange$ = new Subject<string>();

const subscription = statusChange$.subscribe(status => {
  console.log('ステータス変更:', status);
});

ここでは、

  • statusChange$:ステータス変更を通知するSubject
  • subscribe():購読を開始
  • subscription:その購読状態を表すオブジェクト

が作られています。

値を流す

ts
statusChange$.next('loading');
statusChange$.next('success');
出力
ステータス変更: loading
ステータス変更: success

購読が解除されていない間は、next()が呼ばれるたびに、
購読している処理に値が届きます。

購読を解除する(unsubscribe)

ts
subscription.unsubscribe();

これ以降は、値を受け取りません。

unsubscribeが必要な場面

unsubscribeが必要かを判断する一番のポイントは、
そのObservableは自動でcompleteするか? という点です。
次のような場面では、自動でcompleteされるため、unsubscribeが不要になります。

  • HTTP通信
    • レスポンスを1回受け取った時点でcompleteする
  • first()/take(1)などのOperatorを使っている場合
    • 処理が終わると自動でcompleteする
  • asyncpipeを使っている場合
    • コンポーネントの破棄時にAngularが自動でunsubscribeしてくれる

終わりに

SubjectとSubscriptionは、
「値をどう流すか」「購読をどう管理するか」 を意識させてくれる仕組みです。
購読がいつ始まり、いつ終わるのかを意識することで、不要な処理やバグを防げるようになります。
RxJSを使う際は、この2点を常にセットで考えることが大切です。

参考

6
3
0

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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?