概要
JavaScriptの非同期といえば、Promise
と async/await
が広く使われている。
だが Rx の中核である Observable
は、それらとは根本的に性質が異なる。
本稿では、PromiseとObservableの決定的な違い、
そしてなぜ「push-based設計」が非同期処理の破綻を防ぐ鍵となるのかを、設計構造と振る舞いから明快に解き明かす。
1. ObservableとPromiseの対比
特性 | Promise | Observable |
---|---|---|
値の数 | 一度きりの「単一値」 | 0回〜無限回の「複数値」 |
実行タイミング | 作成時に即実行 |
subscribe() されるまで遅延評価 |
キャンセル可能性 | 不可(外部制御できない) |
unsubscribe() で明示的に停止可能 |
同期 vs 非同期 | 必ず非同期 | 同期・非同期の両方に対応 |
構成/合成の容易さ | then() チェーン | 豊富なオペレータで関数的に合成可能 |
2. Promiseの本質:pull-basedな単一処理
const p = new Promise((resolve) => {
console.log("start")
resolve(42)
})
p.then((v) => console.log("resolved", v))
-
Promise
は 「1回きりの非同期イベント」 - 実行は定義と同時(
then()
に関係なく)
3. Observableの本質:push-basedなストリーム
import { Observable } from 'rxjs'
const obs = new Observable<number>((subscriber) => {
subscriber.next(1)
subscriber.next(2)
subscriber.complete()
})
obs.subscribe((v) => console.log('Received:', v))
-
Observable
は値の発行者 - 観測者が購読しない限り実行されない(=遅延評価)
4. push vs pull:設計思想の対比
✅ pull型(Promise):
- 消費者側が「必要なタイミングで値を取りに行く」
- モデル:
const x = getValue()
✅ push型(Observable):
- 発行者側が「値を流す」、消費者はそれを観測する
- モデル:
onValue(x => doSomething(x))
この違いは、制御権がどちらにあるかに直結する。
→ イベントストリームや非同期の流れはpushの方が自然
5. 実用的差分:キャンセルと制御
❌ Promiseの不可避な非同期
const p = new Promise((resolve) => {
setTimeout(() => resolve('done'), 3000)
})
// キャンセルできない。止められない。
✅ Observableの制御可能な非同期
import { interval } from 'rxjs'
const obs = interval(1000)
const sub = obs.subscribe((v) => console.log('tick', v))
setTimeout(() => sub.unsubscribe(), 4000) // 4秒で止める
→ Observableは購読解除が可能。
→ アニメーション、UIイベント、リアルタイム通信において致命的な差となる
6. 実装モデルで見る違い
// Promiseは即時実行、変更できない
const p = new Promise(() => console.log("実行された"))
// Observableは subscribe されるまで何も起きない
const o = new Observable(() => console.log("観測された"))
→ 「定義 = 実行」ではない構造が、Rxの柔軟性の源
よくある誤解と対策
❌ ObservableはPromiseの高機能版
→ ✅ 異なる概念。Observableはイベント・時間を統合したストリーム処理モデル
❌ async/awaitで十分
→ ✅ 確かに簡単。しかし、継続的・複数の非同期処理には限界がある
→ UI入力、WebSocket、監視処理などではRx的構造が不可欠
❌ Rxは覚えることが多すぎる
→ ✅ 最初に必要なのはpush/pullの思想の違いだけ。演算子は構造が分かれば覚える必要なし
結語
Observableは「非同期を扱う構造の一つ」ではない。
時間・状態・イベントを“構造化されたストリーム”として設計する哲学そのものである。
-
Promise
が「未来の1つの値」だとすれば -
Observable
は「未来に流れ続ける情報の川」である
リアクティブ設計とは、
“非同期の断片をつなぎ合わせ、秩序あるストリームとして設計に組み込むことで、制御不能な非同期を掌握するアーキテクチャである。”