buffalo.js文件分析(一)
--ZTE广州研发中心
//建立Buffalo类,属性定义
var Buffalo = Class.create();
Buffalo.BOCLASS="_BUFFALO_OBJECT_CLASS_";
Buffalo.VERSION="2.0";
//buffalo的方法定义
Buffalo.prototype = {
//初始化函数定义,函数名initialize是在Class里面定义的,其它函数是用户定义的。
参数gateway:网关,字符串变量,网关请求将被送到web.xml定义的servlet里面去处理
参数async:异步还是同步,布尔变量
参数events:事件,是一个对象
参数options:一个任意类型的对象
initialize: function(gateway, async, events, options) {
//属性定义,属性名称是任意取的,只要能体现其含义就可以了。
this.gateway = gateway;
this.transport = null; //一个XmlHttp对象,用于提交用户请求,初值为空
if (typeof(async) == 'undefined') {
this.async = true;
} else {
this.async = async;
}
this.currentCallback = new Function(); //回调函数,用于接收服务器返回信息
this.setEvents(events); //设置事件,在下面有说明
this.queue = []; //请求队列,buffalo将所有的请求都先放到请求队列中
this.requesting = false; //请求状态,没有请求
this.options = {timeout:30000}; //设置options属性timeout初值
Object.extend(this.options, options || {}); //将参数options属性和方法复制到当前options,
//这里的options || {}是非常有技巧的写法,如果options不空,将复制options属性和方法,否则,将{}对象的属性复制到当前
options,{}表示空对象,其实也是什么也不复制,这里所说的 当前指this.
},
getGateway : function() { return this.gateway;},
setEvents: function(events) { //设置事件函数
this.events = { //事件初始化
onLoading: Buffalo.Default.showLoading, //设置加载页面时的处理,通常显示"正在处理..."等文本和图片
onFinish: new Function(),
onException: null,
onError: Buffalo.Default.showError, //设置出错时的处理,通常显示出错的文本和图片
onTimeout: new Function()
};
Object.extend(this.events, events || {}); //复制参数events的属性和方法到当前events
},
//远程调用的关键函数
_remoteCall: function(url, buffaloCall, callback) {
this.requesting = true; //设置正在请求处理
this.transport = XmlHttp.create(); //建立一个XmlHttp对象,如果是IE,则XmlHttp对象是一个ActiveXObject类型
try {
this.transport.open("POST", url, this.async); //用POST打开指定的URL,Ajax中post和get没有区别
this.transport.setRequestHeader("X-Buffalo-Version", Buffalo.VERSION); //设置meta
this.transport.setRequestHeader("Content-Type", "text/xml;charset=utf-8");
this.transport.send(buffaloCall.xml()); //buffaloCall是Buffalo.Call对象,buffaloCall.xml()是一个包含方法名和参数的XML字符串,send函数将buffaloCall.xml()字符串和URL送到ApplicationServlet类处理,ApplicationServlet调用RequestWorker接口的processRequest方法处理,processRequest调用ServiceInvoker接口处理,这里用接口的概念是因为这些接口用很多类似的类来实现的,ServiceInvoker调用ClassUtil.invokeMethod,最后调用的函数是java.lang.reflect.Method.invoke()函数执行
} catch (e) {
this.events.onError(this.transport); //用Buffalo.Default.showError()函数显示出错信息
this.events["onLoading"](false); //不显示"buffalo loading... ",这里写法和this.events.onLoading(false)一样
return;
}
this.requestTime = new Date();
this.timeoutHandle = new PeriodicalExecuter(this._timeoutChecker.bind(this), 0.5);
//bind函数是一个非常特殊的函数,本人认为主要用于把this指针传到函数体内,使得在_timeoutChecker里面可以使用this指针,否则, _timeoutChecker将得不到this。这里定义PeriodicalExecuter对象里面有个定/时器timer,定时器每隔一段时间执行eriodicalExecuter对象里面的onTimerEvent方法,onTimerEvent方法里面执行一个callback函数,就是这里的第一个参数this._timeoutChecker.bind(this).
this.currentCallback = callback;
if (this.async) {
this.transport.onreadystatechange = this.onStateChange.bind(this); //把onStateChange函数赋给XmlHttp的
//onreadystatechange方法
this.events["onLoading"](true); //显示"buffalo loading... "等类似字样
} else {
this.response(); //执行response方法,在后面定义
}
},
_timeoutChecker: function() { //超时检查,超时则执行onTimeout事件,并清除计时器
if ((new Date() - this.requestTime) > this.options.timeout) { //超时
this.events["onTimeout"](); //执行onTimeout事件
this.timeoutHandle.stop(); //清除计时器,timeoutHandle在初始化时,设置了一个计时器
}
},
nextRemoteCall : function() { //请求队列里面取一用户请求,执行用户请求
if (this.queue.length <= 0) return ;
var command = this.queue.shift();
this._remoteCall(command.url, command.call, command.callback);
},
//远程请求,service里面包含了类和方法名,params是方法参数,
remoteCall: function(service, params, callback) {
var serviceMethodPair = this._splitServiceMethod(service);
var newUrl = this.gateway+"/buffalo/"+serviceMethodPair[0];
var call = new Buffalo.Call(serviceMethodPair[1]);
for (var i = 0; i < params.length; i++) {
call.addParameter(params[i]);
}
this.queue.push({url:newUrl, call: call, callback: callback}); //将请求压入队列
if (!this.requesting) {
this.nextRemoteCall(); //没有正在执行的请求时,执行用户请求
}
},
_splitServiceMethod: function(service) { //返回类和方法名
var idx = service.lastIndexOf(".");
var serviceId = service.substring(0,idx);
var method = service.substring(idx+1,service.length);
return [serviceId, method];
},
onStateChange: function(){ //如果处理服务器完成处理,则执行response
if (this.transport.readyState == 4) {
this.response();
}
},
response : function() {
this.timeoutHandle.stop(); //清除计时器,timeoutHandle在初始化时,设置了一个计时器
this.events["onLoading"](false); //不显示"buffalo loading... ",
if (this.transport.responseText && this.transport.status == '200') { //成功返回
var reply = new Buffalo.Reply(this.transport); //建立一个Buffalo.Reply对象
if (reply.isFault()) { //根节点的类型是否是"fault","fault"表示返回错误节点信息
if (this.events["onException"]) { //定义了异常处理函数
this.events["onException"](reply.getResult()); //显示返回的错误节点信息
} else {
Buffalo.Default.showException(reply.getResult()); //调用buBuffalo.Default对象的showException函数
this.currentCallback(reply); //调用currentCallback函数处理返回结果
}
} else {
this.currentCallback(reply); //调用currentCallback函数处理返回结果
}
this.events["onFinish"](reply);
this.requesting = false;
this.nextRemoteCall(); //处理下一个请求
} else { //出错处理
this.events["onError"](this.transport);
this.requesting = false;
}
}
}
------未完待续