原名JSPackager
源代码在线查看: request.js
/**
* XMLHttpRequest请求包装内,默认为同步方式。
* 若希望使用异步方式,请设置请求选项{asynchronous:true}
* 请覆盖[onStart,onReceiving,onSuccess,onFailure,onFinish]等事件回调函数,以添加自定义行为
* eg:
*
* new Request(url,{asynchronous:true})
* .setSuccessListener (function(){
* alert('success')
* })
* .setFailureListener (function(){
* alert('fail')
* })
* .send({param1:1});
*
* @constructor
* @param url 请求地址
* @param options 请求选项
* @see #createOptions();
*/
function Request(url,options) {
/** @protected */
this.transport = new XMLHttpRequest();
/** @protected */
this.url = url;
/** @protected */
this.options = this.createOptions(options);
var _this = this;
this.onreadystatechange = function(){
switch(_this.transport.readyState){
case 0: //(未初始化) 对象已建立,但是尚未初始化(尚未调用open方法)
break;
case 1: // (初始化) 对象已建立,尚未调用send方法
break;
case 2: // (发送数据) send方法已调用,但是当前的状态及http头未知
if(_this.onStart){
_this.onStart();
}
break;
case 3: // (数据传送中) 已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误,
if(_this.onReceiving){
_this.onReceiving();
}
break;
case 4: // (完成) 数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据
if(_this.isSuccess() == false){
if(_this.onFailure){
_this.onFailure();
}
}else{
if(_this.onSuccess){
_this.onSuccess();
}
}
if(_this.onFinish){
_this.onFinish();
}
this.free = true;
_this.transport.onreadystatechange = function(){};
break;
}
};
this.free = true;
};
/**
* 发送请求
* @public
* @return Request本身
*/
Request.prototype.send = function(params){
this.free = false;
this.transport.onreadystatechange = this.onreadystatechange;
var headers = this.options.headers;
params = this.buildQueryString(params);
if (this.options.method == 'post') {
this.transport.open(this.options.method, this.url,this.options.asynchronous);
headers['Content-type'] = this.options.contentType;
/* Force "Connection: close" for Mozilla browsers to work around
* a bug where XMLHttpReqeuest sends an incorrect Content-length
* header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType){
headers['Connection'] = 'close';
}
}else{
this.transport.open(this.options.method, this.url+(this.url.match(/\?/) ? '&' : '?') + params,this.options.asynchronous);
}
for(var n in headers){
//$log.debug(n,headers[n]);
this.transport.setRequestHeader(n,headers[n]);
}
this.transport.send(this.options.method == 'post'?params:null);
return this;
};
/**
* 该对象是否空闲(是否可再发送请求).
* @see #send(params);
* @protected
*/
Request.prototype.isFree = function(){
return this.free;
}
/**
* 创建的请求选项.
* 将在一个默认的选项上添加指定的信息。
* @protected
* @param options 用户指定的选项
* @return {object} 请求选项
*/
Request.prototype.createOptions = function(){
var alias = {
//"method":"method",
//"contentType":"contentType",
//"sendCookie":"sendCookie",
//"asynchronous":"asynchronous",
"asyn":"asynchronous"
};
function Creator(options){
this.headers = {"Accept":"'text/javascript, text/html, application/xml, text/xml, */*'"};
for(var n in options){
var n = alias[n] || n;
if(n == "headers"){
var headers = options[n];
for(var n in headers){
this.headers[n2] = headers[n2];
}
}else{
this[n] = options[n];
}
}
}
Creator.prototype = {
method: 'get',
asynchronous: false,
contentType: 'application/x-www-form-urlencoded'
}
return function(options){
return new Creator(options);
}
}();
/**
* 判断请求是否成功
* @public
* @return boolean || null 成败或未知(null)
*/
Request.prototype.isSuccess = function() {
if(this.transport.status == null || this.transport.status == 0){
return null;
}else{
return this.transport.status >= 200 &&
this.transport.status < 300;
}
};
/**
* 请求开始的事件回调函数.
* 以开始发送数据计
* @public
*/
Request.prototype.onStart = function(){};
/**
* 设置请求开始的事件回调函数.
* @public
* @return Request本身
*/
Request.prototype.setStartListener = function(listener){
this.onStart = listener;
return this;
};
/**
* 开始接受数据事件回调函数.
* readState = 3
* @public
*/
Request.prototype.onReceiving = function(){};
/**
* 设置开始接受数据事件回调函数.
* @public
* @return Request本身
*/
Request.prototype.setReceivingListener = function(listener){
this.onReceiving = listener;
return this;
};
/**
* 请求成功的事件回调函数
* @public
*/
Request.prototype.onSuccess = function(){};
/**
* 设置请求成功的事件回调函数
* @public
* @return Request本身
*/
Request.prototype.setSuccessListener = function(listener){
this.onSuccess = listener;
return this;
};
/**
* 请求失败的事件回调函数
* @public
*/
Request.prototype.onFailure = function(){};
/**
* 设置请求失败的事件回调函数
* @public
* @return Request本身
*/
Request.prototype.setFailureListener = function(listener){
this.onFailure = listener;
return this;
};
/**
* 请求结束的事件回调函数
* 该事件发生在onSuccess 或者 onFailure之后,
* 是最后一个回调函数,可以做一些公共的清理操作,一般不设置,令其为空.
* @public
*/
Request.prototype.onFinish = function(){};
/**
* 设置请求结束的事件回调函数
* @public
* @return Request本身
*/
Request.prototype.setFinishListener = function(listener){
this.onFinish = listener;
return this;
};
/**
* 当前请求响应头
* @public
* @return String
*/
Request.prototype.getHeader = function(name) {
if(this.transport.readyState >= 3){
return this.transport.getResponseHeader(name);
}else{
$log.error("response not complete");
}
};
/**
* 将当前请求返回文本当脚本程序执行
* @public
* @return 执行结果
*/
Request.prototype.evalResult = function() {
if(this.transport.readyState == 4){
return eval(this.transport.responseText);
}else{
$log.error("response not complete");
}
};
/**
* 将当前请求返回数据
* @public
* @return 文本 或 XMLDocument
*/
Request.prototype.getResult = function(){
if(/\/xml/.test(this.getHeader("Content-Type"))){
return this.getXML();
}else{
return this.getText();
}
};
/**
* 将当前请求返回XMLDocument
* @public
* @return XMLDocument
*/
Request.prototype.getXML = function() {
if(this.transport.readyState == 4){
return this.transport.responseXML;
}else{
$log.error("response not complete");
}
};
/**
* 将当前请求返回XMLDocument文本
* @public
* @return String
*/
Request.prototype.getText = function() {
if(this.transport.readyState >= 3){
return this.transport.responseText;
}else{
$log.error("response not complete");
}
};
/**
* 根据params参数构建http参数表达式
* 尚未支持多级,有待完善
* @public
* @return String
*/
Request.prototype.buildQueryString = function(params){
if(typeof params == 'string'){
return params;
}else if(params instanceof Array){
return params.join('&');
}else if(params instanceof Object){
var paramStr = "";
for(var n in params){
if(paramStr.length>0){
paramStr+= "&"
}
paramStr+= encodeURIComponent(n)+"="+encodeURIComponent(params[n]);
}
return paramStr;
}else{
return params;
}
}