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 相关文章推荐
JavaScript之Getters和Setters 平台支持等详细介绍
Dec 07 Javascript
jQuery判断密码强度实现思路及代码
Apr 24 Javascript
纯javascript响应式树形菜单效果
Nov 10 Javascript
用jQuery实现优酷首页轮播图
Jan 09 Javascript
基于Vuejs和Element的注册插件的编写方法
Jul 03 Javascript
js实现随机点名小功能
Aug 17 Javascript
bootstrap3中container与container_fluid外层容器的区别讲解
Dec 04 Javascript
vue-cli+webpack项目 修改项目名称的方法
Feb 28 Javascript
改变vue请求过来的数据中的某一项值的方法(详解)
Mar 08 Javascript
webpack打包react项目的实现方法
Jun 21 Javascript
在Vue项目中使用snapshot测试的具体使用
Apr 16 Javascript
SpringBoot+Vue开发之Login校验规则、实现登录和重置事件
Oct 19 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
VML绘图板②脚本--VMLgraph.js、XMLtool.js
2006/10/09 PHP
PHP获取文件后缀名的三个函数
2012/10/15 PHP
Laravel框架搜索分页功能示例
2019/02/01 PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
2020/02/21 PHP
php7 图形用户界面GUI 开发示例
2020/02/22 PHP
半角全角相互转换的js函数
2009/10/16 Javascript
JavaScript去掉空格的方法集合
2010/12/28 Javascript
javascript 弹出层组件(升级版)
2011/05/12 Javascript
JS中令人发指的valueOf方法介绍
2013/02/22 Javascript
js无刷新操作table的行和列
2014/03/27 Javascript
无刷新上传文件并返回自定义值
2015/06/11 Javascript
js添加绑定事件的方法
2016/05/15 Javascript
浅谈Jquery中Ajax异步请求中的async参数的作用
2016/06/06 Javascript
JavaScript自学笔记(必看篇)
2016/06/23 Javascript
js输入框使用正则表达式校验输入内容的实例
2017/02/12 Javascript
vue实现全选和反选功能
2017/08/31 Javascript
微信小程序实现YDUI的ScrollNav组件
2018/02/02 Javascript
vue权限管理系统的实现代码
2019/01/17 Javascript
微信小程序开发技巧汇总
2019/07/15 Javascript
Vue——前端生成二维码的示例
2020/12/19 Vue.js
Python变量和数据类型详解
2017/02/15 Python
Python通过Pygame绘制移动的矩形实例代码
2018/01/03 Python
详解Python并发编程之创建多线程的几种方法
2019/08/23 Python
Python统计文本词汇出现次数的实例代码
2020/02/27 Python
520使用Python实现“我爱你”表白
2020/05/20 Python
html5 css3实例教程 一款html5和css3实现的小机器人走路动画
2014/10/20 HTML / CSS
iRobot官网:改变生活的家用机器人品牌
2016/09/20 全球购物
aden + anais官方网站:婴儿襁褓、毯子、尿布和服装
2017/06/21 全球购物
业务员的岗位职责
2014/03/15 职场文书
中秋节活动总结
2014/08/29 职场文书
村干部群众路线整改措施思想汇报
2014/10/12 职场文书
公务员检讨书
2014/11/01 职场文书
校本课程教学计划
2015/01/19 职场文书
有关西游记的读书笔记
2015/06/25 职场文书
python标准库ElementTree处理xml
2022/05/20 Python
Go gorilla/sessions库安装使用
2022/08/14 Golang