Dev Study
Angular コース

21. Observable と RxJS — 時間とともに届く値

前のレッスンの HttpClient は、結果を Observable という入れ物で返します。Observable は「これから(非同期に)届くかもしれない値の流れ」を表すもので、subscribe(購読)して初めて処理が動き、値が届くとコールバックが呼ばれます。1回きりの通信結果も、何度も発火するイベントも、同じ Observable として扱えるのが特徴です。

RxJS は、その Observable を加工するための演算子(オペレータ)を集めたライブラリです。pipe() の中に map(値を変換)や filter(条件で絞る)などを並べると、届いた値を流れの中で次々に加工できます。Angular の通信やフォームの値の監視など、非同期の処理の多くがこの仕組みの上に成り立っています。

つまずきやすいのは、subscribe しっぱなしにすると購読が残り続け、メモリリークの原因になることです。テンプレートでは async パイプ({{ data$ | async }})を使うと、購読と解除をフレームワークが自動でやってくれるため安全で簡潔です。手動で subscribe したときは、ngOnDestroy での解除や takeUntilDestroyed() を忘れないようにします。

サンプルコード(フレームワーク環境が必要なため表示のみ)

import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs';
import { AsyncPipe } from '@angular/common';

type User = { id: number; name: string };

@Component({
  selector: 'app-user-names',
  imports: [AsyncPipe],
  // async パイプが購読と解除を自動で行う
  template: '@for (name of names$ | async; track name) { <p>{{ name }}</p> }',
})
export class UserNamesComponent {
  private http = inject(HttpClient);

  // pipe + map で「Userの配列」を「名前の配列」に変換する流れを作る
  names$ = this.http
    .get<User[]>('/api/users')
    .pipe(map((users) => users.map((u) => u.name)));
}
公式ドキュメントで詳しく ↗