您好,欢迎访问一九零五行业门户网

javascript 构建一个xmlhttp对象池合理创建和使用xmlhttp对象_javascript技巧

如果我们在客户端频繁使用ajax技术,那么我们就不得不多次创建xmlhttp对象。当然,如您所知,我们可以改进创建的方式,比如使用全局变量来缓存一个实例(客户端的单例模式?!),对于同步方式的通信,这是很有效的,但是这样的方式对于异步通信会出现问题,因为没有了进程的堵塞,用户可能在上一次通信未完成时再次调用同一个xmlhttp实例,这样不等前一个调用的回调函数触发,前一次调用就被“覆盖”掉了(也就代表前一次调用失败)。建立一个保持xmlhttp实例的池,好处显而易见,最明显的优点就是我们不会创建冗余对象,同时也不会出现在同一个正在被调用的xmlhttp实例上出现再次被操作的情况。
具体实现思路:
我们使用一个数组来存储已创建的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 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 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 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 // 当定义了成功回调函数时,执行成功回调函数
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 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#里的异步处理回调方法,它们在原理上其实是相通的。 哈哈,现在终于想通了, 真是太骄傲,太有出息了,想到就兴奋!
其它类似信息

推荐信息