Skip to content

MessagePassing

uupaa edited this page Dec 12, 2016 · 2 revisions

Namespace

Entity of MessagePassing module is located in the global.WebModule.MessagePassing.
If you want publish to global namespace.

MessagePassing モジュールの実体は、global.WebModule.MessagePassing にあります。
global 名前空間に直接公開する事もできます。その場合は global.MessagePassing でもアクセス可能になります。

API

MessagePassing.prototype.id

MessagePassing#id(subscriber:SubscriberObject):SubscriberIDString は、MessagePassing#register で登録された Subscriber の ID を返します。

// Subscriber Object
var A = {
    inbox: function(selector) {
        return true;
    }
};

// Subscriber Class
class B {
    inbox(selector) {
        return true;
    }
};

var b = new B();
var mp = new MessagePassing().register(A).register(b);

mp.id(A) // -> "Object.1"
mp.id(b) // -> "B.2"

MessagePassing.prototype.subscribers

MessagePassing#subscribers:SubscriberIDStringArray は、MessagePassing#register で登録されている Subscriber ID の配列を返します。

var A = { inbox: function(selector) { return true; } };
var B = { inbox: function(selector) { return true; } };
var C = { inbox: function(selector) { return true; } };

var mp = new MessagePassing();

mp.register(A).register(B).register(C);
mp.subscribers // -> ["Object.1", "Object.2", "Object.3"];

MessagePassing.prototype.register

MessagePassing#register(subscriber:SubscriberObject, allowSelectors:SelectorStringArray|SelectorString = "ping"):this は、メッセージを受信する Subscriber を登録します。

  • Subscriber は inbox メソッドを持っている必要があります。inbox メソッドが無ければエラーになります
  • allowSelectors に指定した文字列と Message#send と Message#post の引数 selector が一致する場合にメッセージが送信されます。異なる場合は無視します(inbox メソッドを呼び出しません)。
var Subscriber = {
        inbox: function(selector) {
            console.log(selector + " World"); // -> "Hello World"
        }
    };

var mp = new MessagePassing();

mp.register(Subscriber, "Hello"); // Subscriber は Hello を受け取ります
mp.id(Subscriber);                // -> "Object.1"
mp.send("Hello");                 // Subscriber.inbox("Hello") が呼ばれます

MessagePassing.prototype.unregister

MessagePassing#unregister(subscriber:SubscriberObject):this は、登録済みの Subscriber を抹消します。

登録を抹消すると Message#send や Message#post でメッセージが届かなくなります。

var A = { inbox: function(selector) { } };
var B = { inbox: function(selector) { } };

var mp = new MessagePassing();

mp.register(A).register(B); // 登録
mp.unregister(A).unregister(B); // 抹消

MessagePassing.prototype.unregisterAll

MessagePassing#unregisterAll():this は、登録済みの Subscriber を全て抹消します。

var A = { inbox: function(selector) { } };
var B = { inbox: function(selector) { } };

var mp = new MessagePassing();

mp.register(A).register(B); // 登録

mp.unregisterAll(); // 全て抹消

MessagePassing.prototype.to

Message.prototype.to

MessagePassing#to(subscriber:SubscriberObject = null, ...):Message は、Message Object を作成し、宛先に subscriber を設定します。

Message#to(subscriber:SubscriberObject = null, ...):Message は、Message Object に subscriber を追加します。

  • subscriber を省略した場合は、登録済みの全ての Subscriber を宛先に設定します(ブロードキャストします)
  • subscriber は to(A, B, C) のように複数指定できます。重複した場合は無視します
var Foo = { inbox: function() {} };
var Bar = { inbox: function() {} };
var Buz = { inbox: function() {} };
var mp = new MessagePassing();

mp.register(Foo).register(Bar).register(Buz);

上記のように Foo, Bar, Buz の3つの Subscriber が登録された状態で…

  1. mp.to(Foo)Foo を宛先に設定した Message Object を返します
  2. mp.to(Foo, Bar)Foo, Bar を宛先に設定した Message Object を返します。mp.to(Foo).to(Bar) と同じ結果になります
  3. mp.to()Foo, Bar, Buz を宛先に設定した Message Object を返します

MessagePassing.prototype.send

Message.prototype.send

Message#send(selector:String, arg:Any = null, ...):AnyObject は Message Object の宛先に指定されている Subscriber の inbox を呼び出し、inbox の戻り値を返します。

  • register(, allowSelectors) と selector が違っている場合は、inbox を呼び出しません

send の戻り値から Subscriber#inbox() メソッドの戻り値を取得する方法は2つあります

  1. 名前で検索

    • MessagePassing#id で Subscriber ID を求め、ID を使って send の戻り値を検索します
    var A = { inbox: function(selector) { return "A"; } };
    var mp = new MessagePassing().register(A, "ping");
    var result = mp.to(A).send("ping");
    
    console.log( result[ mp.id(A) ] ); // -> "A"
  2. 配列から取得

    • send の戻り値を配列と見立て値を取得します
    var A = { inbox: function(selector) { return "A"; } };
    var B = { inbox: function(selector) { return "B"; } };
    var mp = new MessagePassing().register(A, "ping").register(B, "ping");
    var result = mp.to(A, B).send("ping");
    
    console.log( result[0], result[1] ); // -> "A" "B"

Subscriber#inbox を呼び出す順番は、以下の通りです。

  • ブロードキャストの場合は、register(subscriber) で登録した順番に inbox メソッドを呼び出します
  • マルチキャスト/ユニキャスト の場合は、to(...) で指定した順番に inbox メソッドを呼び出します

オプションとして可変長引数を指定可能です。引数は inbox にそのまま渡されます

// Message#send(selector, arg1, arg2) は A#inbox(selector, arg1, arg2) の形で渡されます

var A = {
    inbox: function(selector, arg1, arg2) {
        return "A" + arg1 + arg2;
    }
};
var mp = new MessagePassing().register(A)

mp.to(A).send("ping", 1, 2)[0]; // -> "A12"

MessagePassing.prototype.post

Message.prototype.post

Message#post(selector:String, arg:Any = null, ...):void と
Message#post(selector:String, arg:Any = null, ..., callback:Function = null):void は宛先に指定されている Subscriber の inbox を呼び出します。callbackが指定されている場合は inbox の戻り値を callback の引数として返します。

send と post には違いが2つあります。

  1. send は同期的に動作しますが、post は非同期的に動作します
  2. post の最後の引数が Function の場合は callback が指定されたものとして扱います
    • callback は callback(result:AnyObject):void の形で全ての inbox の呼び出しが終わったタイミングでコールバックします。
    • inbox に渡される引数は1つ減ります(callback の分減ります)
var A = { inbox: function(selector) { return "A"; } };
var B = { inbox: function(selector) { return "B"; } };
var mp = new MessagePassing().register(A, "ping").register(B, "ping");

var result = mp.to(A, B).post("ping", function(result) {

    console.log( result[ mp.id(A) ] );   // -> "A"
    console.log( result[0], result[1] ); // -> "A" "B"
});

MessagePassing.prototype.send

MessagePassing#send():AnyObject は登録されている全ての Subscriber に対して Broadcast を行い inbox の戻り値を返します。

MessagePassing#send は Message#send よりも低コストです。

var A = { inbox: function(selector) { return "A"; } };
var B = { inbox: function(selector) { return "B"; } };
var mp = new MessagePassing();
mp.register(A).register(B);

// 以下のコードはどちらも同じ結果になります
mp.send("ping");        // MessagePassing#send
mp.to().send("ping");   // Message#send

MessagePassing.prototype.post

MessagePassing#post():AnyObject は登録されている全ての Subscriber に対して Broadcast を行い inbox の戻り値を返します。

MessagePassing#post は Message#post よりも低コストです。

var A = { inbox: function(selector) { return "A"; } };
var B = { inbox: function(selector) { return "B"; } };
var mp = new MessagePassing();
mp.register(A).register(B);

// 以下のコードはどちらも同じ結果になります
mp.post("ping", function(result) { });       // MessagePassing#post
mp.to().post("ping", function(result) { });  // Message#post