FluxはFacebookの提唱するクライアントサイドのWebアプリケーション(ユーザーインターフェース)を開発するためのアプリケーションアーキテクチャです。FluxはView、Store、Dispacther、Actionの4つの役割に分けられます。今回その中でもFluxの中心となる「Dispatcher」の部分について理解を深めるために、Fluxのドキュメント内のDispatcherの部分を翻訳してみました。Dispatcherがわかれば、Fluxでの実装についてもそれなりにわかるようになると思うので、拙い訳ですが、ぜひ参考にしてみてください。
はじめに – FluxとDispatcher
Fluxは「クライアントサイドのWebアプリケーション(ユーザーインターフェース)を開発するためのアプリケーションアーキテクチャ」です。MVCやMVVMなどと同類です。Fluxは役割によってView、Store、Dispatcher、Actionの4つの部品にわけられます。それぞれの役割は、よく以下の図によって説明されています。データの流れを一方向性にすることで、ReactによるViewの実装をよりシンプルにすることができます。
Fluxを使ったアプリケーションを開発する際に、Dispatcherの実装が肝になってきます。言葉で説明するより、以下を見ていただけると、それがよくわかると思います。
これから先は、以下のFluxのドキュメントを日本語に訳したものとなります。
Dispatcher (日本語訳)
Dispatcher is used to broadcast payloads to registered callbacks. This is different from generic pub-sub systems in two ways:
Dispatcherは登録されたコールバックにペイロードを一斉送信するために使われます。これは2つの点において一般的なpub-subシステム(発行/購読システム)と異なります。
・Callbacks are not subscribed to particular events. Every payload is dispatched to every registered callback.
・Callbacks can be deferred in whole or part until other callbacks have been executed.
- コールバックは個々のイベントを購読しない。すべてのペイロードはすべての登録されたコールバックに送られる。
- コールバックは他のコールバックが実行されるまで、すべてもしくは一部延期されうる。
Check out Dispatcher.js for the source code.
ソースコードを通してDispatcher.jsをチェックしましょう。
API
・register(function callback): string Registers a callback to be invoked with every dispatched payload. Returns a token that can be used with waitFor().
・unregister(string id): void Removes a callback based on its token.
・waitFor(array<string> ids): void Waits for the callbacks specified to be invoked before continuing execution of the current callback. This method should only be used by a callback in response to a dispatched payload.
・dispatch(object payload): void Dispatches a payload to all registered callbacks.
・isDispatching(): boolean Is this Dispatcher currently dispatching.
- register(function callback): string 送信されたすべてのペイロードと一緒に呼び出されるコールバックを登録します。waitFor()メソッドで使われるトークンを返します。
- unregister(string id): void トークンを元にしてコールバックを削除します。
- waitFor(array<string> ids): void 連続している現在のコールバックの実行前に呼び出されるように指定されたコールバックを待ち受けます。このメソッドは送信されたペイロードに応じたコールバックによってのみ使われるべきです。
- dispatch(object payload): void ペイロードをすべての登録されたコールバックに送ります。
- isDispatching(): boolean このDispatcherが現在送信しているかどうかの状態を示します。
Example – 例
For example, consider this hypothetical flight destination form, which selects a default city when a country is selected:
例えば、これを国が選択されたらデフォルトの都市を選択する仮定の飛行目的地フォームを通して考えてみましょう。
When a user changes the selected city, we dispatch the payload:
ユーザーが選択された都市を変更した時、ペイロードをdispatchします。
This payload is digested by CityStore:
このペイロードはCityStoreによって読み込まれます。
When the user selects a country, we dispatch the payload:
ユーザーが国を選択した時、ペイロードをdispatchします。
This payload is digested by both stores:
このペイロードは両方のstoreによって読み込まれます。
When the callback to update CountryStore is registered, we save a reference to the returned token. Using this token with waitFor(), we can guarantee that CountryStore is updated before the callback that updates CityStore needs to query its data.
CountryStoreをアップデートするためのコールバックが登録された時、返されたトークンに参照をセーブします。このトークンをwaitFor()メソッドに渡すことで、CityStoreをアップデートするコールバックがそのデータを照会する必要が出てくる前に、CountryStoreがアップデートされることを保証することが可能となります。
The usage of waitFor() can be chained, for example:
以下の例のように、waitFor()メソッドの使用は連鎖されます。
The country-update payload will be guaranteed to invoke the stores’ registered callbacks in order: CountryStore, CityStore, then FlightPriceStore.
country-updateペイロードは、storeの登録されたコールバックを CountryStore, CityStore, それからFlightPriceStoreの順で呼び出すことを保証されるようになります。
Dispatcherについてポイント解説
翻訳は以上となります。うまく訳せていない部分もあるかと思うので、Dispatcherについて要点をまとめてみました。
Dispatcher(dispatcher.js)のポイント
- register()メソッドにコールバック関数をセットすると、トークンが返される。
- register()メソッドによって返されたトークンは、waitFor()メソッドに引数としてセットして使う。
- dispatch()メソッドを実行すると、引数にセットされたペイロードが、register()メソッドによって登録されているコールバック関数に送られる(複数あればすべてのコールバック関数に)。
- dispatch()メソッドを実行すると、すべてのコールバック関数に送られる。イベントを監視してコールバック関数を管理するような仕組みをとっていない。どのコールバック関数を実行させるかは、ペイロード内の値で識別する。
- register()メソッドで登録されたコールバック関数が複数ある場合、waitFor()メソッドを使って優先順位をコントロールする。
- コールバック関数AとBがあったとして、Aより先にBを実行したい場合は、Aの関数内でBのトークンをセットしたwaitFor()メソッドを実行させる。Aの実行を待たせて、Bが先に実行されるようになる。
Dispatcher(dispatcher.js)の準備
Fluxは、以下のコマンドでインストールできます。
Dispatcherは、以下のように requireして読み込みます。
Dispatcher(dispatcher.js)を使ったFluxの実装について
上記のポイントを踏まえて、dispatcher.jsを使ったFluxの実装方法を簡単にまとめておきます。
View
- Reactで実装。
- onClickなどのイベントによって、Actionを呼び出す。
- Storeの状態を監視し、状況に応じてsetState()メソッドを使ってViewを更新。
Action
- dispatch()メソッドの引数にオブジェクトリテラル形式のデーター(ペイロード)をセット(Action Creator)。
- Storeがアクションを識別できるようにアクションタイプ属性を持たせる。
- ViewでActionが発生したら、対応するdispatch()メソッドを実行。
Dispatcher
- dispatch()メソッドが実行されたら、引数にセットされているオブジェクト(ペイロード)をStoreに送信。
Store
- register()メソッドにコールパック関数を登録。
- Dispatcherによってペイロードが送られて来たら、登録したすべてのコールバック関数を実行。
- それぞれのコールバック関数は、ペイロードのアクションタイプ属性を見てアクションに対応すべきか否かを判断。
- コールパック関数が複数ある場合は、waitFor()メソッドを使って順番を制御。
- 状況に応じて、イベントを発行し、View(React)に通知。
参考サイト & 書籍
最後にFluxやDispatcherについての理解をより深めるのに参考となるサイトを紹介します。
- Flux – ActionsとDispacher(日本語訳) – Qiita
- Fluxデザインパターンの勉強 – Qiita
- FacebookのFluxアーキテクチャの始め方 Part 1 | プログラミング | POSTD
- Tutorial – Todo List – Flux
- FluxのDispatcherとAction周りのことでもやもやしていることを晒してみる – SlideShare
Fluxについての専門的な書籍はまだ出ていないと思います。そんな中で、今年の7月に出版された『WEB+DB PRESS vol.87』に掲載の伊藤直也さんによるFluxの記事(全9頁)は、これからFluxを勉強する方にとっては貴重な情報源になると思います。React単体のコードからFluxを適用させたコードに変えることによって、Fluxの実装のポイントをわかりやすく説明してくれています。自分もこの記事でFluxの理解を深めることができました。最後に紹介しておきます。(ES2015の記事もあるので、かなりオススメです!)
コメント