Pub/Subによるメッセージ処理
DojoにはいわゆるPub/Sub(またはPublish/Subscribe、 出版・購読型モデルなどとも)と呼ばれる、 コンポーネント間でメッセージをやり取りするプログラミング・パターンをサポートするメソッドが実装されています。 Pub/Subによるメッセージ応答はウィジェットを多数使う本格的なアプリケーションではよく利用されます。
Pub/Subを利用する
Pub/Subを利用するには、"トピック"と呼ばれるメッセージを送り手側のコンポーネントがdojo.publish()で送信します。 dojo.subscribe()でそのトピックを受信すると登録していた受け手はトピックが送出されたとき反応して登録した処理が実行されます。次の表は関連するメソッドの一覧です。
メソッド | 説明 |
---|---|
dojo.publish(/*String*/ topic, /*Array*/ args) | topic名のトピックをアプリケーション全体に通知します。トピックが通知されると、同トピックを購読するコンポーネントの登録された処理が起動します。argsには登録した関数を呼ぶときの引数を配列で指定します。 |
dojo.subscribe(/*String*/ topic, /*Object|null*/ context, /*String|Function*/ method) | topic名トピックを購読します。購読したトピックがdojo.publish()によって通知されたときに登録したmethodが起動し、その処理のコンテキスト(this)がオブジェクトcontextになります。 |
dojo.unsubscribe() | topic名トピックの購読をやめます。以降、topicが通知されても登録していた処理は起動しません。 |
次のサンプル・コードは、ボタンが押されたときに購入処理を開始する意味の "PurchasingItems" というトピックを発行し、別のコンポーネントがそれを購読していて表示を変化させるサンプルです。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Pub/Subによるイベント処理</title> <style> @import url("../dojo-release-1.5.0/dojo/resources/dojo.css"); @import url("../dojo-release-1.5.0/dijit/themes/claro/claro.css"); </style> <script type="text/javascript" src="../dojo-release-1.5.0/dojo/dojo.js" djConfig="parseOnLoad: true"></script> <script type="text/javascript"> dojo.require("dojo.parse"); // DojoがHTMLをパースするのに必要 dojo.require("dijit.form.Button"); function onButtonClick(event) { // topicの発行 dojo.publish("PurchasingItems"); } dojo.addOnLoad(function() { dojo.subscribe("PurchasingItems", null, function() { dojo.byId("messageDiv").innerHTML += "購入処理を開始します" + "<br />"; }); }); </script> </head> <body class="claro"> <div id="button1" dojoType="dijit.form.Button" onClick="onButtonClick">トピックの発行</div> <div id="messageDiv"></div> </body> </html>
トピック名は自由につけることができますが、よく考えてイベントの意味を端的に表すわかりやすい文字列にすべきでしょう。またイベントが特有のコンポーネントに紐付いているものならば / を用いて階層化するのもよいでしょう(たとえば "PurchaseButton/StartProcessing" のように)。Dijitではツリー・ウィジェットなどで内部的に階層形式のトピックを発行しています。
Pub/Subとdojo.connect()の使いどころ
ウィジェットのイベントが起きたとき反応して何か処理を行うには、対象のイベントに対してdojo.connect()で処理を登録するやり方もありますね。Pub/Subとどう使い分ければよいでしょうか。
Pub/Subモデルのメリットがその指針となります。つまり
- 対象のコンポーネント間を疎結合に保ちたいとき
- あるイベントに対して将来多数のウィジェットが反応すると予想されるとき(現時点では確定していない)
などには目的のコンポーネントに直接dojo.connect()するのではなくPub/Subを利用すべきです。