三、 數(shù)據(jù)結(jié)構(gòu)
Messenger系統(tǒng)里最重要的數(shù)據(jù)結(jié)構(gòu)自然是message本身。一直在考慮是否有必要為Message定義一個接口,后來覺得也許用數(shù)組性能會更好,所以就直接使用一個數(shù)組來定義message的格式了?紤]到一般情況的應(yīng)用,這個 msg 數(shù)組包含5個元素,即 msg[0] 至 msg[4], 如圖:
 具體的字段定義為:
1. msg[0]: Priority, 數(shù)值類型, 調(diào)度系統(tǒng)會優(yōu)先調(diào)度緊急消息,僅當沒有緊急消息時,調(diào)度普通消息,工作于 post 模式,取值范圍(0,1), 0 表示緊急, 1 表示普通。
2. msg[1]: Device, 字串類型, 窗口標識,Messenger系統(tǒng)支持在彈出窗口以及iframe的對象間的通信,本字段表示消息接收者位于哪個窗口或iframe。默認為 null,表示本窗口。
3. msg[2]: [Recvs...], 數(shù)組類型, 消息接收者的id數(shù)組,消息發(fā)送者可以指定消息被某一個或某幾個特定的接收者接收。默認為 null,表示所有訂閱該消息的接收者都可以接收。
4. msg[3]: MsgID, 字串類型, 消息種類的id, 對應(yīng) what。
5. msg[4]: MsgData, 任意類型, 消息的內(nèi)容, 是通信雙方希望傳遞的實際內(nèi)容,由通信雙方約定具體類型。
2、 Registry的結(jié)構(gòu)
Messenger是一個基于訂閱/發(fā)布模式(subscribe/publish)的實現(xiàn),自然要維護一個訂閱者的數(shù)據(jù)庫, 當然在具體的設(shè)計和實現(xiàn)中,不會也不必引入數(shù)據(jù)庫的概念,但如下的一個起碼的數(shù)據(jù)表是必需的。
這樣的一張表,在實現(xiàn)中,可以用下圖的數(shù)據(jù)結(jié)構(gòu)來具體實現(xiàn):
在JavaScript,可以非常容易地實現(xiàn)上圖:
- /**
-
* Define the EventQueue class based on subscribe/publish mode
-
*/
-
js.awt.EventQueue = function(){
-
/**
-
* Registry of subscribtion
-
*
-
* key is "what"
-
* value is a list of the pair (who, where)
-
*/
-
var R = {};
-
-
/**
-
* Subscribe a message from EventQueue
-
*
-
* @param what, the message id
-
* @param who, the message listener
-
* @param where, the message handler
-
*/
-
this.register = function(what, who, where){
-
var recvs = R[what];
-
if(recvs == null){
-
recvs = [];
-
R[what] = recvs;
-
}
-
-
recvs.push({listener:who, handler:where});
-
-
};
-
-
}.$extend(ls.lang.Object);
3、 Message隊列的結(jié)構(gòu)
這個Messenger系統(tǒng)最大的特點是支持異步消息遞送,即消息發(fā)送者調(diào)用post來發(fā)送消息。 所謂異步消息遞送分為兩個階段, 第一階段,消息發(fā)送者調(diào)用post方法,消息直接進入Messenger里的一個隊列中,post方法立即返回。 第二階段, Messenger的調(diào)度系統(tǒng)從消息隊列中取出一條消息分發(fā)給所有訂閱者。 考慮到可能會有消息優(yōu)先級的應(yīng)用需求,在這個Messenger系統(tǒng)里,采用一個簡單的方案來實現(xiàn)所謂的優(yōu)先級隊列,即雙隊列,一個放緊急消息,一個放普通消息。post消息時,根據(jù)消息優(yōu)先級放入不同的隊列,當調(diào)度系統(tǒng)分發(fā)消息時,僅當緊急隊列為空,才分發(fā)普通隊列的消息。
在JavaScript里實現(xiàn)這樣的一個隊列,可以是異常的簡單。
- /**
-
* Define the EventQueue class based on subscribe/publish mode
-
*/
-
js.awt.EventQueue = function(){
-
/**
-
* Message queue
-
*
-
* Q[0] for urgent message
-
* Q[1] for general message
-
*/
-
var Q = [[],[]];
-
-
var _get = function(){
-
var msg = Q[0].shift();
-
msg = (msg == undefined) ? Q[1].shift() : msg;
-
return msg;
-
};
-
-
var _put = function(msg){
-
Q[msg[0]].push(msg);
-
};
-
-
/**
-
* Test whether the message queue is empty
-
*/
-
this.isEmpty = function(){
-
return (Q[0].length + Q[1].length) === 0;
-
};
-
-
/**
-
* Message sender use this method to post a message and
-
* return immediately
-
*
-
* @param msg
-
* +----------+----------+------------+----------+-------------+
-
* | PRI | Device | [recvs..] | msgId | msgData |
-
* +----------+----------+------------+----------+-------------+
-
*/
-
this.post = function(msg){
-
_put(msg);
-
};
-
-
/**
-
* Schedule system use this method to dispatch a message to
-
* listeners
-
*
-
*/
-
this.dispatch = function(){
-
var msg = _get(), ex;
-
if(msg == undefined) return;
-
-
// TODO:
-
-
};
-
-
-
}.$extend(ls.lang.Object);
未完待續(xù)... |