js自定义消息机制研究学习(四)之杂七杂八
终于要写完了~~^_^,期间给同事做了一次培训,写一次,讲一次的好处是,再次加深了自己对于消息、事件以及观察者模式的理解。
对我来说,讲清楚比写代码要难上很多。
这里分享一些与消息机制相关的一些杂七杂八的内容。
一、可测试的代码
早些时候,我向锐同学描述我的js程序结构,他问了我一个问题:你的js代码可测么?
我蒙了~虽然一直关注敏捷,一直也向往测试驱动开发,但还从没想过js代码的可测试(当然,也有测试,但基本上整测加局部测试),没有想过js的测试驱动。
当时,我迟疑了一会,才说应该是可测的。
写完上一篇文章(原谅我,觉得太简单,直接写的,忘了测试驱动),回头看了看,还好,基于消息的代码确实可以做到可测。
比如:
Animal
function Animal(config){ config=config || {}; var othis=this; this.name=config["name"] || "Anonymous"; this.x=config["x"] || 0; var toward=1;//右:1,左-1 var __timeout=0; var __speed=5; //说 this.say=function(str) { this.trigger({type:"say",msg:str}); return str; } //停 this.stop=function() { clearTimeout(__timeout); this.trigger({type:"stop",x:this.x}); return this.x; } //跑动 this.run=function(speed) { __speed=speed || __speed; this.x+=__speed*toward; __timeout=setTimeout(function(){ othis.run();},100); this.trigger({type:"run",x:this.x,toward:toward,speed:__speed}); return {x:this.x,toward:toward,speed:__speed}; } //向左转 this.turnLeft=function() { toward=-1; this.trigger({type:"turn",toward:toward}); return toward; } //向右转 this.turnRight=function() { toward=1; this.trigger({type:"turn",toward:toward}); return toward; }}方法都是有返回值,这样便于我们做一些单元测试,除了单元测试,我们还要做一些基于消息的机制的测试,构造一个伪对象去侦听Animal对象发送的消息
但这个Animal并不完全,还有一些不可测的,比如toward,它是完全封闭在内部的一个变量,你想要知道Animal的对象前进的方向,就有些困难。
不过这主要源于Animal这个类得不完全,但我们不能为了访问toward而直接把它修改为this.toward暴露出来,这样别人有可能赋一个错误的值:this.toward=100;仔细看一下代码,公开toward让人可以随别赋值是很危险的一件事情。好的方式,写一个getToward()方法。
一种难以测试的实现是示例这样写的:
Logger
///记录器function Logger(){ var dom=document.getElementById("log"); var log=function(str) { var time=new Date(); this.dom.innerHTML+="<br/>"+str+'<span style="color:gray">('+time.getHours()+":"+time.getMinutes()+":"+time.getSeconds()+")</span>"; }; this.handler=function(data,p){ switch(data.type) { case "say": this.log(p.name+" 说:"+data.msg); break; case "stop": this.log('<span style="color:green">'+p.name+" 停在了"+data.x+'</span>'); break; case "turn": this.log(p.name+" 转向了"+(data.toward==1?"右":"左")); break; } }; }Logger对象只暴露了一个handler方法,它写死了dom。
当然它在示例运行中会很好的执行自己的职责。为了测试它,我们首先保证页面上要有一个id为log的dom元素,还要伪造一个消息对象,如Animal对象去给它发消息。这让我们又一种整体测试的感觉。
这不是一个好的示例。
总体而言,消息的密闭性会给测试带来一些麻烦。实际中,我们一个函数的调用可能会触发很多个消息,而不只是一个。而这些消息名又洒落在了代码的各处。除非你仔细的阅读代码,否则很可能会遗漏消息。
像Animal一样,尽量做到一个方法值触发一个消息,或者相反、相关联的消息。如果是一些大的对象,把消息名罗列在对象开始前得注释代码中,也便于他们维护调试。
二、冒泡的消息
在刚开始的时候,我曾实现过消息的冒泡,就像是内部a标签的click事件会冒泡到外部div一样。
消息的冒泡示例:
a.bind("test",b) b.bind("test",c) c.bind("test",d)
如果你实现了冒泡,a的test消息会沿着a->b->c->d的路径一直传送到d
简单的实现呢,就是每个对象的handler函数,直接trigger一下传进来的消息,这样的方式并没有实现自动化。一个简单改动如下:
View Code
function trigger(Y){ var queue =[]; var qs=this.__MSG_QS__ || {}; var sqs=this.__STATIC_MSG_QS__|| {}; queue= queue.concat(qs[Y.type] || []); queue= queue.concat(sqs[Y.type] || []); for (var a = 0, X = queue.length; a < X; a++) { if(queue[a].handler) { queue[a].handler(Y,this)  
补充:Web开发 , Jsp ,