RxJSで学ぶリアクティブプログラミング

## はじめに
この記事はアイスタイル [Advent Calendar 2024](https://qiita.com/advent-calendar/2024/istyle) 7日目の記事です。

[アットコスメ](https://www.cosme.net/) のバックエンド開発を担当しているkuriyamayです。

今年もアドベントカレンダーへの参加となります。

過去の記事はこちらから。

* 2020年
[kubernetes(k8s)を構築してデプロイやスケールで遊んでみた](https://techblog.istyle.co.jp/archives/6296)
* 2021年
[Java SE 11(Java Silver)を受験した話](https://techblog.istyle.co.jp/archives/8225)
* 2022年
[curry化と部分適用をJavaで](https://qiita.com/kuriyamay/items/45f69ceda78d88acd871)
[curry化と部分適用をJavaで ~命名編~](https://qiita.com/kuriyamay/items/8a808d0c8cbbfde10e13)
* 2023年
[CQRSとEventSourcingに挑戦](https://qiita.com/kuriyamay/items/a4a978a6698b14cc8bff)

今年はRxJSについてつらつらと書いていこうと思います。

## RxJSへのきっかけ

もともとはJavaのSpring WebFluxを使ってリアクティブプログラミングを学んでいました。
その後、業務で新しいアプリケーションを作成する機会があり、Node.js(TypeScript)とNestJSを採用したことをきっかけに、RxJSの学習を始めました。

NestJSは公式でRxJSをサポートしており、フレームワーク内部でRxJSを利用しています。
そのため、非同期処理を扱う際にObservablesを使用できます。

せっかくNestJSを選んだので、RxJSの利点を活かしたアプリケーションを作りたいと思い、より深く学ぶことを決めました。

## RxJSの概要と魅力
### RxJSとは何か

RxJS（Reactive Extensions for JavaScript）は、イベントや非同期処理を「データストリーム」として扱うための強力なライブラリです。
特徴は以下の通りです：
* Reactive Extensions for JavaScriptの略称
* イベントや非同期処理をデータストリームとして扱う
* Rxの概念は多くの言語で共通
    * 例: RxJava（Java用）、RxPy（Python用）、RxAndroid（Android用）、RxKotlin（Kotlin用）

公式ドキュメント: [RxJS Documentation](https://rxjs.dev/)

また、Spring WebFluxはJava向けのリアクティブなWebフレームワークで、似たようなリアクティブプログラミングの概念を採用しています。

Spring WebFlux公式: [Spring WebFlux Documentation](https://docs.spring.io/spring-framework/reference/web/webflux.html)

### なぜRxJSを使うのか

Rxの概念を学べば、他の言語やフレームワーク（例: AngularやReact）でも応用可能です。
また、RxJSを使うことで、以下のメリットが得られます：
* 宣言的なコードが書ける: 複雑な処理もシンプルに記述可能
* 非同期処理に強い: イベント、タイマー、APIレスポンスなどを一貫したインターフェースで扱える
* リアルタイム処理に最適: マイクロサービスやリアルタイムアプリケーションの開発に向いている


## RxJSの基本概念
### リアクティブプログラミングとは

リアクティブプログラミングは、データの流れ（ストリーム）と変化に反応するプログラミングパラダイムです。
その特徴は以下の通りです：
* データの変化に応じて自動的に処理が実行される
* 命令型プログラミングと対比される宣言型のアプローチ
* 非同期処理やイベント駆動型システムの設計に適している

リアクティブプログラミングでは、すべてのデータ（イベント・タイマー・APIレスポンスなど）は「ストリーム」として扱われ、即座に反応できる仕組みが特徴です。

### Observable/Observer/Subscription

RxJSの基本要素を見てみましょう。
1. Observable
    * データストリームの「作成者」
    * データの流れ（イベント）を定義
    * 遅延実行型：subscribeを呼び出すまで実行されない
2. Observer
    * データストリームの「受信者」
    * next（データの受信）、error（エラー）、complete（完了）の3つのメソッドを持つ
3. Subscription
    * ストリームの「コントローラー」
    * unsubscribeを呼び出すことでストリームを停止できる

以下は具体例です：

```js
// Observableを作成
const observable = new Observable((subscriber) => {
  // データを次のストリームへ送信
  subscriber.next(1);
  subscriber.next(2);
  subscriber.complete(); // 完了を通知する
});

// Observableを購読（subscribe）
observable.subscribe({
  next: (value) => console.log(`Next: ${value}`), // 値を受信した場合に実行
  error: (err) => console.error(`Error: ${err}`), // エラー発生時に実行
  complete: () => console.log('Completed'), // ストリームが完了した時に実行
});
```


## RxJSの動作原理
配列とRxJSの違いを比較しながら、内部的な挙動を見ていきます。

### 通常の配列

```js
const result = [1, 2, 3].map((x) => x * 2);
console.log(result); // 出力: 2, 4, 6
```

### RxJSのObservable
```js
of(1, 2, 3)
  .pipe(map((value) => value * 2))
  .subscribe(console.log); // 出力: 2, 4, 6
```

#### 配列とObservableの違い
出力結果は同じですが、Observableは遅延実行を採用しており、非同期データを効率的に扱う点で配列とは根本的に異なります。
次に、配列とObservableの違いを表で見てみましょう。

| 特徴           | 配列                           | Observable                        |
|----------------|--------------------------------|-----------------------------------|
| 実行タイミング | 即時実行                      | 遅延実行 (subscribeで開始)       |
| データの扱い   | 静的データ（同期的）          | ストリーム（同期/非同期両対応） |
| 再利用性       | 配列は状態を保持しない        | Observableは再利用可能           |

Observableは非同期処理に対応している点が大きな特徴です。
たとえば、リアルタイムデータやAPIレスポンスのような動的データを一貫したインターフェースで扱うことができます。
また、subscribeを呼び出すたびに新しいストリームを開始できるため、同じ処理を再利用するのも容易です。

## まとめ
* RxJSの学習コストは高いがその価値はある
* 一度習得すれば他言語やフレームワークでも応用可能
* ストリームの流れを意識した宣言的なコードを書けると楽しい

最後まで読んでいただき、ありがとうございました！

引き続きアイスタイル [Advent Calendar 2024](https://qiita.com/advent-calendar/2024/istyle) をお楽しみください。