RxJS の Disposable とその種類

この記事は [bouzuya's RxJS Advent Calendar 2015](http://www.adventar.org/calendars/1200) の 18 日目かつ RxJS Advent Calendar 2015 の 18 日目です。

# はじめに

今日は `Disposable` とその種類を見ていきます。個人的な理由で時間がないので一覧とメモになっています。

[RxJS 4.0.7](https://github.com/Reactive-Extensions/RxJS/tree/v4.0.7) を対象にしています。

# Disposable とその種類

## Disposable

- [`Disposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/disposable.md)
- [`Disposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/disposable.js)

`Disposable` は `dispose` を持つ class です。`subscribe` の戻り値は `Disposable` です。`dispose` することで unsubscribe (例えば `removeEventListener` ) されます。Operator ごとに様々な `Disposable` を使っています。ちなみに概要は [2 日目にも書きました](http://qiita.com/bouzuya/items/63a6dfca0e3ebb0f5268#disposable)。

`Disposable` の constructor は `action` を引数に取り、`dispose` 呼び出しで一度だけ `action` を実行します。

大した関数は持たないので実装を挙げます。

- `Disposable.create` ... `(action) => new Disposable(action)`
- `Disposable.empty` ... `{ dispose: noop }`
- `Disposable.isDisposable` ... `(d) => d && isFunction(d.dispose)`
- `Disposable.prototype.dispose` ... 前述の通りです。

Disposable にはいくつかの種類があります。

- [`Disposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/disposable.js) [`Disposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/disposable.md)
- [`BinaryDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/binarydisposable.js)
- [`CompositeDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/compositedisposable.js) [`CompositeDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/compositedisposable.md)
- [`NAryDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/binarydisposable.js)
- [`RefCountDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/refcountdisposable.js) [`RefCountDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/refcountdisposable.md)
- [`ScheduledDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/scheduleddisposable.js)
- [`SerialDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/booleandisposable.js) [`SerialDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/serialdisposable.md)
- [`SingleAssignmentDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/booleandisposable.js) [`SingleAssignmentDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/singleassignmentdisposable.md)

これらは superclass の実装を必要としないせいか、`Disposable` を継承していません。また `Disposable` を名前に含まないものの `dispose` を持ち `Disposable` として扱われている `AutoDetachObserver` などもあります。

## BinaryDisposable

- [`BinaryDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/binarydisposable.js)

`BinaryDisposable` の constructor は 2 つの `Disposable` を引数に取ります。`dispose` で、それらの 2 つの `Disposable` の `dispose` を呼び出します。

## CompositeDisposable

- [`CompositeDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/compositedisposable.md)
- [`CompositeDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/compositedisposable.js)

`CompositeDisposable` の constructor は複数の `Disposable` または `Disposable` の配列を引数に取ります。また `add` / `remove` で、それらの `Disposable` へ追加・削除できます。`dispose` で、それらのすべての `Disposable` の `dispose` を呼び出します。

`remove` は `dispose` されていなければ削除できます。`add` は既に `CompositeDisposable` が `dispose` されていれば、追加した瞬間に `dispose` されます。

## NAryDisposable

- [`NAryDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/binarydisposable.js)

`CompositeDisposable` から `add` / `remove` を除いたものです。

## RefCountDisposable

- [`RefCountDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/refcountdisposable.md)
- [`RefCountDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/refcountdisposable.js)

constructor では `Disposable` を引数に取ります。`getDisposable` で `count++` し、`dispose` で `count--` します。`count === 0` のとき、constructor で取った `Disposable` を `dispose` します。

ちなみに `Observable.prototype.refCount` で返されるわけではありません。

## ScheduledDisposable

- [`ScheduledDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/scheduleddisposable.js)

`ScheduledDisposable` の constructor は `scheduler` と `disposable` を引数に取り、 `dispose` を呼び出されたときに `scheduler` に従って `dispose` を呼び出します。

## SerialDisposable

- [`SerialDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/serialdisposable.md)
- [`SerialDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/booleandisposable.js)

`getDisposable` / `setDisposable` を持ち、ひとつの `disposable` を内部に保持します。`setDisposable` を複数回呼び出すと、保持している `disposable` を `dispose` して新しい `Disposable` を保持します。

## SingleAssignmentDisposable

- [`SingleAssignmentDisposable` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/disposables/singleassignmentdisposable.md)
- [`SingleAssignmentDisposable` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/disposables/booleandisposable.js)

`getDispoable` / `setDisposable` を持ち、ひとつの `disposable` を内部に保持します。`setDisposable` を複数回呼び出すと、既に `disposable` を保持している場合は例外を投げます。

# おわりに

今日は `Disposable` とその種類を確認しました。

個人的な理由で時間がなく、どう使われるのかなどに触れられていないのが残念です。