具体实现思路:
我们使用一个数组来存储已创建的xmlhttp对象实例,然后每次调用从池中去取一个实例。xmlhttp实例通讯完毕后我们不用做任何处置,因为它自身的readyState属性可以标识出它是否可用,如果当时没有空闲的xmlhttp实例,且池中的实例数小于最大实例个数,那么就创建一个新的实例并放入池中。重新改进的实现代码如下:
代码
//
封装XMLHTTP的MyAjaxObj类
var MyAjaxObj = new Object();
var maxXmlHttpCount = 5 ; // 最多5个xmlhttp对象存在
MyAjaxObj.reqList = []; // 可以清空里面的项
MyAjaxObj.getFreeObj = function () {
var req = null ;
var len = this .reqList.length;
// 先从当前的池里取
for ( var i = 0 ; i < len; i ++ ) {
if ( this .reqList[i]) {
if ( this .reqList[i].readyState == 4 || this .reqList[i].readyState == 0 ) {
req = this .reqList[i];
break ;
}
}
}
// 如果没有闲置的对象,自己独立创建
if (req == null ) {
if ( this .reqList.length < maxXmlHttpCount) {
req = getXmlHttp();
this .reqList.push(req);
}
}
return req;
}
// 创建一个XMLHTTP对象,兼容不同的浏览器
function getXmlHttp() {
var xmlHttp = false ;
var arrSignatures = [ " MSXML2.XMLHTTP.5.0 " , " MSXML2.XMLHTTP.4.0 " ,
" MSXML2.XMLHTTP.3.0 " , " MSXML2.XMLHTTP " ,
" Microsoft.XMLHTTP " ];
for ( var i = 0 ; i < arrSignatures.length; i ++ ) {
try {
xmlHttp = new ActiveXObject(arrSignatures[i]);
return xmlHttp;
}
catch (oError) {
xmlHttp = false ; // ignore
}
}
// throw new Error("MSXML is not installed on your system.");
if ( ! xmlHttp && typeof XMLHttpRequest != ' undefined ' ) {
xmlHttp = new XMLHttpRequest();
}
return xmlHttp;
}
/* 封装XMLHTTP向服务器发送请求的操作
url:向服务器请求的路径;method:请求的方法,即是get/post;***callback:当服务器成功返回结果时,调用的函数(类似c#回调函数)***
data:向服务器请求时附带的数据;urlencoded:url是否编码;cached:是否使用缓存; callBackError;当服务器返回错误时调用的函数
*/
MyAjaxObj.send = function (url, method, callback, data, urlencoded, cached, callBackError) {
var req = this .getFreeObj(); // 从池里或者直接实例化一个XMLHTTP的实例
// 当XMLHTTP的请求状态发生改变时调用 (核心处理函数)
req.onreadystatechange = function () {
// 当请求已经加载
if (req.readyState == 4 ) {
// 当请求返回成功
if (req.status == 200 ) { // 或者 req.status < 400
// 当定义了成功回调函数时,执行成功回调函数
if (callback)
callback(req, data);
}
// 当请求返回错误
else {
// 当定义了失败回调函数时,执行失败回调函数
if (callBackError)
callBackError(req, data);
}
// 有池的管理,我们可以省却释放资源的方法
// try {
// delete req;
// req = null;
// }
// catch (e) {
// alert(e.message);
// }
}
}
// 如果以POST方式回发服务器
if (method.toUpperCase() == " POST " ) {
req.open( " POST " , url, true );
// 请求是否需要缓存(只有在req.open之后才可以设置此项)
if (cached)
req.setRequestHeader( " If-Modified-Since " , " 0 " );
// 请求需要编码
if (urlencoded)
req.setRequestHeader( ' Content-Type ' , ' application/x-www-form-urlencoded ' );
req.send(data);
MyAjaxObj.reqList.push(req);
}
// 以GET方式请求
else {
req.open( " GET " , url, true );
// 请求是否需要缓存
if (cached)
req.setRequestHeader( " If-Modified-Since " , " 0 " );
req.send( null );
MyAjaxObj.reqList.push(req);
}
return req;
}
// 全部清除XMLHTTP数组元素,释放资源
MyAjaxObj.clearReqList = function () {
var len = MyAjaxObj.reqList.length;
for ( var i = 0 ; i < len; i ++ ) {
var req = MyAjaxObj.reqList[i];
if (req) {
try {
delete req;
} catch (e) { }
}
}
MyAjaxObj.reqList = [];
}
// 进一步封装XMLHTTP以POST方式发送请求时的代码
// isClear:是否清除XMLHTTP数组的所有元素;其他参数的意义见 MyAjaxObj.send
MyAjaxObj.sendPost = function (url, data, callback, isClear, isCached, callBackError) {
if (isClear) {
MyAjaxObj.clearReqList();
}
MyAjaxObj.send(url, " POST " , callback, data, true , isCached, callBackError); // post方法需要编码
}
// 进一步封装XMLHTTP以GET方式发送请求时的代码
MyAjaxObj.sendGet = function (url, args, callback, isClear, isCached, callBackError) {
if (isClear)
MyAjaxObj.clearReqList();
return MyAjaxObj.send(url, " GET " , callback, args, false , isCached, callBackError);
}
var MyAjaxObj = new Object();
var maxXmlHttpCount = 5 ; // 最多5个xmlhttp对象存在
MyAjaxObj.reqList = []; // 可以清空里面的项
MyAjaxObj.getFreeObj = function () {
var req = null ;
var len = this .reqList.length;
// 先从当前的池里取
for ( var i = 0 ; i < len; i ++ ) {
if ( this .reqList[i]) {
if ( this .reqList[i].readyState == 4 || this .reqList[i].readyState == 0 ) {
req = this .reqList[i];
break ;
}
}
}
// 如果没有闲置的对象,自己独立创建
if (req == null ) {
if ( this .reqList.length < maxXmlHttpCount) {
req = getXmlHttp();
this .reqList.push(req);
}
}
return req;
}
// 创建一个XMLHTTP对象,兼容不同的浏览器
function getXmlHttp() {
var xmlHttp = false ;
var arrSignatures = [ " MSXML2.XMLHTTP.5.0 " , " MSXML2.XMLHTTP.4.0 " ,
" MSXML2.XMLHTTP.3.0 " , " MSXML2.XMLHTTP " ,
" Microsoft.XMLHTTP " ];
for ( var i = 0 ; i < arrSignatures.length; i ++ ) {
try {
xmlHttp = new ActiveXObject(arrSignatures[i]);
return xmlHttp;
}
catch (oError) {
xmlHttp = false ; // ignore
}
}
// throw new Error("MSXML is not installed on your system.");
if ( ! xmlHttp && typeof XMLHttpRequest != ' undefined ' ) {
xmlHttp = new XMLHttpRequest();
}
return xmlHttp;
}
/* 封装XMLHTTP向服务器发送请求的操作
url:向服务器请求的路径;method:请求的方法,即是get/post;***callback:当服务器成功返回结果时,调用的函数(类似c#回调函数)***
data:向服务器请求时附带的数据;urlencoded:url是否编码;cached:是否使用缓存; callBackError;当服务器返回错误时调用的函数
*/
MyAjaxObj.send = function (url, method, callback, data, urlencoded, cached, callBackError) {
var req = this .getFreeObj(); // 从池里或者直接实例化一个XMLHTTP的实例
// 当XMLHTTP的请求状态发生改变时调用 (核心处理函数)
req.onreadystatechange = function () {
// 当请求已经加载
if (req.readyState == 4 ) {
// 当请求返回成功
if (req.status == 200 ) { // 或者 req.status < 400
// 当定义了成功回调函数时,执行成功回调函数
if (callback)
callback(req, data);
}
// 当请求返回错误
else {
// 当定义了失败回调函数时,执行失败回调函数
if (callBackError)
callBackError(req, data);
}
// 有池的管理,我们可以省却释放资源的方法
// try {
// delete req;
// req = null;
// }
// catch (e) {
// alert(e.message);
// }
}
}
// 如果以POST方式回发服务器
if (method.toUpperCase() == " POST " ) {
req.open( " POST " , url, true );
// 请求是否需要缓存(只有在req.open之后才可以设置此项)
if (cached)
req.setRequestHeader( " If-Modified-Since " , " 0 " );
// 请求需要编码
if (urlencoded)
req.setRequestHeader( ' Content-Type ' , ' application/x-www-form-urlencoded ' );
req.send(data);
MyAjaxObj.reqList.push(req);
}
// 以GET方式请求
else {
req.open( " GET " , url, true );
// 请求是否需要缓存
if (cached)
req.setRequestHeader( " If-Modified-Since " , " 0 " );
req.send( null );
MyAjaxObj.reqList.push(req);
}
return req;
}
// 全部清除XMLHTTP数组元素,释放资源
MyAjaxObj.clearReqList = function () {
var len = MyAjaxObj.reqList.length;
for ( var i = 0 ; i < len; i ++ ) {
var req = MyAjaxObj.reqList[i];
if (req) {
try {
delete req;
} catch (e) { }
}
}
MyAjaxObj.reqList = [];
}
// 进一步封装XMLHTTP以POST方式发送请求时的代码
// isClear:是否清除XMLHTTP数组的所有元素;其他参数的意义见 MyAjaxObj.send
MyAjaxObj.sendPost = function (url, data, callback, isClear, isCached, callBackError) {
if (isClear) {
MyAjaxObj.clearReqList();
}
MyAjaxObj.send(url, " POST " , callback, data, true , isCached, callBackError); // post方法需要编码
}
// 进一步封装XMLHTTP以GET方式发送请求时的代码
MyAjaxObj.sendGet = function (url, args, callback, isClear, isCached, callBackError) {
if (isClear)
MyAjaxObj.clearReqList();
return MyAjaxObj.send(url, " GET " , callback, args, false , isCached, callBackError);
}
最后再ps:上周周末和一个哥们聊天的时候谈到ajax应用中的xmlhttp对象。那哥们ms很“虔诚”地问我说xmlhttp怎么就异步通信了。我当时竟然毫不思索地说因为这个对象处理我们的请求调用是“异步”的(当然可以设置成同步的,不过这是一句废话),当前这个请求不会影响其他的操作。这个回答是很“官方”的,显然没有说到问题的本质。哥们,您的眼神儿有必要那么bs人么?现在稍作分析,个人认为其实每个xmlhttp异步请求都会触发一个回调函数,这个回调函数的调用不影响其他的操作,这个方法才是“异步”。如果对比c#里的异步处理回调方法,它们在原理上其实是相通的。 哈哈,现在终于想通了, 真是太骄傲,太有出息了,想到就兴奋!