タスクのイベントハンドラ

 HTMLは元々イベントドリブン方式であり、各タグに対応したハンドラをタスクのイベントハンドラとすることもできる。例えば、以下のような実装である。(※Event.observe()はprototype.jsのAPIである)

(function(){
var task=Sys.getContext();
Event.observe(Sys.$('button1'),'click',function(ev){
	var l=task.lock();
	// anything to do 
	task.unlock(l);
});
})();

 小規模なアプリケーションであれば、このような実装でもいいが、例えば、タスクに優先度をつけたいとか、イベントに遅延をつけたいとか、ユーザ定義イベントを投げたいなどと思ったときに、この方式だけでは都合が悪くなる。論理タスクの優先度とはイベントの優先度であり、それを実装する最も簡単な方法は複数のイベントキューを持つことである。

イベントキューの実装は次のようなものとなる。

Queue=function(){this.q=new Array();}
Queue.prototype={
	push:function(e){this.q.push(e);},
	pop:function(){if(this.q.length>0){return this.q.shift();}return null;},
	size:function(){return this.q.length;},
	empty:function(){return this.q.length==0;}
};

このキューを用いて、
1) initイベント: oninitが呼ばれるまで実行されないイベント。oninitの後は遅延しない。
2) interイベント: 優先度の高いイベント。
3) timerイベント: 一定時間後に発火するタイマー。
といったものを実装した例が下記例である。

Sys={
	q_inter:new Queue,
	q:new Queue,
	q_init:new Queue,
	init_:function(){
		this.dispatchEntry_();
		this.q=this.q_init;
		this.dispatch_();
	},
	send:function(ev,delay){
		if(delay){
			switch(delay){
			case "inter":this.q_inter.push(ev);break;
			case "init":this.q_init.push(ev);break;
			default:setTimeout(this.notifier(ev),delay);break;}}
		else{this.q.push(ev);}
	},
	notify:function(ev,dom){
		this.dispatchEntry_();
		if(dom){ev.dom=dom;}
		this.handler_(ev);
		this.dispatch_();
	},
	dispatch_:function(){
		var q=this.q;
		var ev;
		ev=q_inter.pop();
		if(ev==null){ev=q.pop();}
		while(ev!=null){
			this.handler_(ev);
			ev=q_inter.pop();
			if(ev==null){ev=q.pop();}
		}
	},
	handler_:function(ev){
		var task=this.tasks[ev.tid];
		if(task){
			var l=task.lock();
			task.handler(ev);
			task.unlock(l);
		}
	},
	observe:function(name, hookname, callback){
		var task=Sys.getContext();
		var tag=Sys.$(name);
		Event.observe(tag,hookname,function(ev){
			var l=task.lock();
			(callback)(ev,tag);
			task.unlock(l);
		});
	}
}

これらAPIの利用方法は下記のようになる。

Sys.observe('button1', 'click', (function(ev,dom){
	Sys.notify(ev,dom);
})(ev,dom));
Sys.send({'type':'test1'});
Sys.send({'type':'test2'},'inter');
Sys.send({'type':'test3'},'init');
Sys.send({'type':'test4'},200);

task1.handler=function(ev){
	switch(ev){
	case 'click':
		switch(ev.dom.id){
		case 'button1':break;
		default:break;}
	case 'test1':break;
	case 'test2':break;
	case 'test3':break;
	case 'test4':break;
	default:break;}
}
カテゴリー: html5_multitask   タグ: , ,   この投稿のパーマリンク

コメントを残す