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


Posted in Javascript onJanuary 15, 2010

如果我们在客户端频繁使用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 < 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#里的异步处理回调方法,它们在原理上其实是相通的。 哈哈,现在终于想通了, 真是太骄傲,太有出息了,想到就兴奋!
Javascript 相关文章推荐
JS中confirm,alert,prompt函数使用区别分析
Apr 01 Javascript
FireFox下XML对象转化成字符串的解决方法
Dec 09 Javascript
javascript的switch用法注意事项分析
Feb 02 Javascript
JavaScript的变量声明提升问题浅析(Hoisting)
Nov 30 Javascript
详解JavaScript中this的指向问题
Jan 20 Javascript
js中的触发事件对象event.srcElement与event.target详解
Mar 15 Javascript
Vue form 表单提交+ajax异步请求+分页效果
Apr 22 Javascript
JS按钮闪烁功能的实现代码
Jul 21 Javascript
vue 中filter的多种用法
Apr 26 Javascript
原生JS实现逼真的图片3D旋转效果详解
Feb 16 Javascript
JavaScript实现图片上传并预览并提交ajax
Sep 30 Javascript
详解钉钉小程序组件之自定义模态框(弹窗封装实现)
Mar 07 Javascript
extjs 为某个事件设置拦截器
Jan 15 #Javascript
利用onresize使得div可以随着屏幕大小而自适应的代码
Jan 15 #Javascript
javascript 不间断的图片滚动并可点击
Jan 15 #Javascript
Span元素的width属性无效果原因及解决方案
Jan 15 #Javascript
javascript实现的基于金山词霸网络翻译的代码
Jan 15 #Javascript
JQuery 引发两次$(document.ready)事件
Jan 15 #Javascript
用jQuery扩展自写的 UI导航
Jan 13 #Javascript
You might like
Zend Guard一些常见问题解答
2008/09/11 PHP
PHP爆绝对路径方法收集整理
2012/09/17 PHP
如何使用PHP实现javascript的escape和unescape函数
2013/06/29 PHP
php自定义加密与解密程序实例
2014/12/31 PHP
PHP生成器简单实例
2015/05/13 PHP
PHP远程调试之XDEBUG
2015/12/29 PHP
如何在PHP中使用AES加密算法加密数据
2020/06/24 PHP
jquery 指南/入门基础
2007/11/30 Javascript
jquery中each方法示例和常用选择器
2014/07/08 Javascript
JavaScript常用脚本汇总(一)
2015/03/04 Javascript
AngularJS页面访问时出现页面闪烁问题的解决
2016/03/06 Javascript
Bootstrap项目实战之子栏目资讯内容
2016/04/25 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
2016/08/23 Javascript
基于Node.js + WebSocket打造即时聊天程序嗨聊
2016/11/29 Javascript
nodejs个人博客开发第五步 分配数据
2017/04/12 NodeJs
Vue.js手风琴菜单组件开发实例
2017/05/16 Javascript
vue-cli项目根据线上环境分别打出测试包和生产包
2018/05/23 Javascript
微信小程序时间轴实现方法示例
2019/01/14 Javascript
easyUI使用分页过滤器对数据进行分页操作实例分析
2020/06/01 Javascript
[41:41]TFT vs Secret Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
在Python中操作字典之setdefault()方法的使用
2015/05/21 Python
Python使用smtplib模块发送电子邮件的流程详解
2016/06/27 Python
Python中json格式数据的编码与解码方法详解
2016/07/01 Python
Python实现二维数组按照某行或列排序的方法【numpy lexsort】
2017/09/22 Python
详解python里的命名规范
2018/07/16 Python
荷兰多品牌网上鞋店:Stoute Schoenen
2017/08/24 全球购物
Lookfantastic瑞典:英国知名美妆购物网站
2018/04/06 全球购物
惠而浦美国官网:Whirlpool.com
2021/01/19 全球购物
介绍一下常见的木马种类
2014/11/15 面试题
SOA面试题:如何在SOA中实现松耦合
2013/07/21 面试题
自主招生自荐信格式
2015/03/04 职场文书
2015年健康教育工作总结
2015/04/10 职场文书
2015年公务员工作总结
2015/04/24 职场文书
就业推荐表院系意见
2015/06/05 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
JavaScript实现优先级队列
2021/12/06 Javascript