三、 数据结构
Messenger系统里最重要的数据结构自然是message本身。一直在考虑是否有必要为Message定义一个接口,后来觉得也许用数组性能会更好,所以就直接使用一个数组来定义message的格式了。考虑到一般情况的应用,这个 msg 数组包含5个元素,即 msg[0] 至 msg[4], 如图:
具体的字段定义为:
1. msg[0]: Priority, 数值类型, 调度系统会优先调度紧急消息,仅当没有紧急消息时,调度普通消息,工作于 post 模式,取值范围(0,1), 0 表示紧急, 1 表示普通。
2. msg[1]: Device, 字串类型, 窗口标识,Messenger系统支持在弹出窗口以及iframe的对象间的通信,本字段表示消息接收者位于哪个窗口或iframe。默认为 null,表示本窗口。
3. msg[2]: [Recvs...], 数组类型, 消息接收者的id数组,消息发送者可以指定消息被某一个或某几个特定的接收者接收。默认为 null,表示所有订阅该消息的接收者都可以接收。
4. msg[3]: MsgID, 字串类型, 消息种类的id, 对应 what。
5. msg[4]: MsgData, 任意类型, 消息的内容, 是通信双方希望传递的实际内容,由通信双方约定具体类型。
2、 Registry的结构
Messenger是一个基于订阅/发布模式(subscribe/publish)的实现,自然要维护一个订阅者的数据库, 当然在具体的设计和实现中,不会也不必引入数据库的概念,但如下的一个起码的数据表是必需的。
这样的一张表,在实现中,可以用下图的数据结构来具体实现:
在JavaScript,可以非常容易地实现上图:
- /**
-
* 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队列的结构
这个Messenger系统最大的特点是支持异步消息递送,即消息发送者调用post来发送消息。 所谓异步消息递送分为两个阶段, 第一阶段,消息发送者调用post方法,消息直接进入Messenger里的一个队列中,post方法立即返回。 第二阶段, Messenger的调度系统从消息队列中取出一条消息分发给所有订阅者。
考虑到可能会有消息优先级的应用需求,在这个Messenger系统里,采用一个简单的方案来实现所谓的优先级队列,即双队列,一个放紧急消息,一个放普通消息。post消息时,根据消息优先级放入不同的队列,当调度系统分发消息时,仅当紧急队列为空,才分发普通队列的消息。
在JavaScript里实现这样的一个队列,可以是异常的简单。
- /**
-
* 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);
未完待续...
阅读(2355) | 评论(0) | 转发(0) |