0
1

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の基本を簡単な計算アプリで身につけよう

Last updated at Posted at 2025-03-08

はじめに

Angularでアプリを開発し始めたとき、RxJSの概念には本当に戸惑いました。「オブザーバブル」「サブジェクト」「オペレータ」という言葉の意味がわからず、コードを書くのに苦労しました。でも実際に使ってみると、非同期処理やイベント処理がとても簡潔に書けるようになり、その威力を実感しました。

RxJS

RxJSは非同期処理を扱うためのライブラリです。その大きな特徴は、すべてをデータの流れとして考えることです。ユーザーのクリック、HTTPリクエスト、時間の経過など、あらゆる出来事をデータの流れとして統一的に扱います。

これにより、複雑な非同期処理を簡潔に書けるようになり、特にAngularアプリケーションでの開発効率が大幅に向上します。

実装

コンポーネントの作成

ng generate component reduce-demo

TypeScript

import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { map, Subject } from 'rxjs';
@Component({
  selector: 'app-reduce-demo',
  standalone: true,
  imports: [FormsModule, CommonModule],
  templateUrl: './reduce-demo.component.html',
  styleUrl: './reduce-demo.component.css'
})
export class ReduceDemoComponent implements OnInit {
  // 入力フィールドの値
  numbersInput = '';
  // 変換後の数値配列
  numbers: number[] = [];
  // 計算結果
  sum = 0;
  // RxJSのSubject - イベントを発行するためのオブジェクト
  private inputSubject = new Subject<string>();
  ngOnInit() {
    // RxJSのパイプラインを設定
    this.inputSubject.pipe(
      // 文字列を数値配列に変換
      map((input: string) => {
        // 例: input = "1, 2, 3"
        return input
          .split(',')                        // ["1", " 2", " 3"]
          .map((n) => Number(n.trim()))      // [1, 2, 3]
          .filter((n) => !isNaN(n));         // 無効な値を除外
      }),
      // 合計を計算
      map(numbers => {
        // 例: numbers = [1, 2, 3]
        this.numbers = numbers;              // 配列を保存
        
        // 合計計算
        return numbers.length > 0
          ? numbers.reduce((acc, curr) => acc + curr, 0)
          : 0;
      })
    ).subscribe(sum => {
      // 例: sum = 6
      this.sum = sum;                        // 結果を保存
    });
  }
  // 入力イベントハンドラ
  processInput() {
    // 入力値をSubjectに送信
    this.inputSubject.next(this.numbersInput);
  }
}

HTML

<div class="container">
  <h2>RxJSを使ったリアクティブな計算</h2>
  
  <!-- 入力フォーム -->
  <div class="input-section">
    <label for="numbers">数値をカンマ区切りで入力してください:</label>
    <input 
      id="numbers" 
      type="text" 
      [(ngModel)]="numbersInput"
      (input)="processInput()"
      placeholder="例: 1,2,3,4,5"
    />
  </div>
  <!-- 結果表示 -->
  <div class="results" *ngIf="numbers.length > 0">
    <h3>結果:</h3>
    <p>入力された数値: {{ numbers.join(', ') }}</p>
    <p>合計: {{ sum }}</p>
  </div>
</div>

RxJSの主要概念と実装解説

初心者にとって難しいRxJSの概念を、計算アプリの実装を通して説明します。

オブザーバブル

オブザーバブルは水が流れる川のようなものです。データが時間とともに流れていきます。この実装では、ユーザー入力の変化が川の流れになっています。入力が変わるたびに、新しいデータが流れていきます。

// Subjectはオブザーバブルの一種です
private inputSubject = new Subject<string>();

// パイプラインの設定(この中をデータが流れていきます)
this.inputSubject.pipe(
  map(...),
  map(...)
)

この例では、inputSubject がオブザーバブルとして機能し、パイプラインを通じてデータが流れていきます。ユーザーが入力フィールドに何かを入力するたびに、そのデータがオブザーバブルに流れ込み、パイプラインで処理されていきます。

サブジェクト

サブジェクトは水源と川の両方の性質を持つものです。水を供給することも、水を流すこともできます。この実装では、inputSubject がサブジェクトとして機能しています。

private inputSubject = new Subject<string>();

ユーザーが入力フォームに何かを入力すると、processInput()メソッドが呼び出され、inputSubject.next()でデータを発行します。これは川に水を流す(データを送り出す)ようなものです。

processInput() {
    // 入力値をSubjectに送信
    this.inputSubject.next(this.numbersInput);
}

また、サブジェクトにはパイプラインが接続されており、流れてきた水(データ)を受け取って処理もします。

オペレータ

オペレータは川に設置されたフィルターのようなものです。流れてくる水(データ)を受け取って、形を変えて次に流します。

この実装では、mapオペレータを使用しています。最初のmapは入力された文字列をカンマで分割し、数値の配列に変換するフィルターです。2番目のmapはその数値配列を合計値に変換するフィルターです。

例えば、ユーザーが 1,2,3 と入力すると、

最初のmapでデータは "1,2,3" から [1,2,3] に変換されます

map((input: string) => {
  return input
    .split(',')
    .map((n) => Number(n.trim()))
    .filter((n) => !isNaN(n));
})

2番目のmapでデータは [1,2,3] から 6 に変換されます

// 合計を計算
map(numbers => {
    // 例: numbers = [1, 2, 3]
    this.numbers = numbers;              // 配列を保存

    // 合計計算
    return numbers.length > 0
      ? numbers.reduce((acc, curr) => acc + curr, 0)
      : 0;
})

サブスクライブ

.subscribe(sum => {
  this.sum = sum;
});

サブスクライブは川の下流に立って、流れてくる水(データ)を受け取ります。

この実装では、subscribeメソッドがその役割を果たしています。パイプラインの最後で変換されたデータ(この場合は合計値)を受け取り、それを使って画面を更新します。ユーザーが 1,2,3 と入力した場合、最終的に 6 という値がサブスクライブの部分に届き、その値がthis.sumに保存されてUIに表示されます。

まとめ

この記事では、RxJSの基本である「オブザーバブル」「サブジェクト」「オペレータ」「サブスクライブ」を簡単な計算アプリで学びました。

RxJSは最初は難しく感じますが、データの流れとして考えれば理解しやすくなります。まずは小さなアプリから始めて、少しずつ慣れていきましょう。RxJSを使いこなせば、より簡潔で保守しやすいコードが書けるようになります。

説明が不十分な点や疑問に思う部分があれば、お気軽にご指摘ください。RxJSについて一緒に理解を深められたら幸いです。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?