在ajax应用中,一般一个页面要同时发送多个请 求,若是只有一个XMLHttpRequest对象,前面的请求还未完成,后面的就会把前面的覆盖掉,若是每次都建立一个新的 XMLHttpRequest对象,也会形成浪费。解决的办法就是建立一个XMLHttpRequset的对象池,若是池里有空闲的对象,则使用此对象, 不然将建立一个新的对象。javascript
下面是我最近写的一个简单的类:
php
/**
* XMLHttpRequest Object Pool
*
* @author legend <legendsky@hotmail.com>
* @link http://www.ugia.cn/?p=85
* @Copyright www.ugia.cn
*/
var XMLHttp = {
_objPool: [],
_getInstance: function ()
{
for (var i = 0; i < this._objPool.length; i ++)
{
if (this._objPool[i].readyState == 0 || this._objPool[i].readyState == 4)
{
return this._objPool[i];
}
}
// IE5中不支持push方法
this._objPool[this._objPool.length] = this._createObj();
return this._objPool[this._objPool.length - 1];
},
_createObj: function ()
{
if (window.XMLHttpRequest)
{
var objXMLHttp = new XMLHttpRequest();
}
else
{
var MSXML = ['MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];
for(var n = 0; n < MSXML.length; n ++)
{
try
{
var objXMLHttp = new ActiveXObject(MSXML[n]);
break;
}
catch(e)
{
}
}
}
// mozilla某些版本没有readyState属性
if (objXMLHttp.readyState == null)
{
objXMLHttp.readyState = 0;
objXMLHttp.addEventListener("load", function ()
{
objXMLHttp.readyState = 4;
if (typeof objXMLHttp.onreadystatechange == "function")
{
objXMLHttp.onreadystatechange();
}
}, false);
}
return objXMLHttp;
},
// 发送请求(方法[post,get], 地址, 数据, 回调函数)
sendReq: function (method, url, data, callback)
{
var objXMLHttp = this._getInstance();
with(objXMLHttp)
{
try
{
// 加随机数防止缓存
if (url.indexOf("?") > 0)
{
url += "&randnum=" + Math.random();
}
else
{
url += "?randnum=" + Math.random();
}
open(method, url, true);
// 设定请求编码方式
setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
send(data);
onreadystatechange = function ()
{
if (objXMLHttp.readyState == 4 && (objXMLHttp.status == 200 || objXMLHttp.status == 304))
{
callback(objXMLHttp);
}
}
}
catch(e)
{
alert(e);
}
}
}
};
html
示例:java
<script type="text/javascript" src="xmlhttp.js"></script>
<script type="text/javascript">
function test(obj)
{
alert(obj.statusText);
}
XMLHttp.sendReq('GET', 'http://www.ugia.cn/wp-data/test.htm', '', test);
XMLHttp.sendReq('GET', 'http://www.ugia.cn/wp-data/test.htm', '', test);
XMLHttp.sendReq('GET', 'http://www.ugia.cn/wp-data/test.htm', '', test);
XMLHttp.sendReq('GET', 'http://www.ugia.cn/wp-data/test.htm', '', test);
alert('Pool length:' + XMLHttp._objPool.length);
</script>
web
demo 下载xmlhttp.jsajax
Permalinkjson
December 22, 2005 @ 7:12 pm数组
大哥哥,你的日志时间超前了吧,已经在BXNA显示了一天了。。。浏览器
December 22, 2005 @ 7:19 pm缓存
我发现这个问题了,后台的时间选项改了改,没管用,帖子时间我也改了。郁闷
再改,改到21号
December 23, 2005 @ 9:12 am
怎么在IE下使用有问题呢?
提示64行第5个字符,缺乏标识符字符串或数字
而后提示XMLHttp未定义
在Firefox使用正常
December 23, 2005 @ 9:39 am
源代码里有中文的注释,是ansi的,若是你的网站或ie下选择编码为UTF-8,可能会致使错误,你把你ie的编码改为gb2312看看,或者去掉文件里的中文注释
December 26, 2005 @ 10:48 am
服务器是否是php5的?可能须要设置一下php.ini。
December 27, 2005 @ 5:28 pm
测试自动转向
December 27, 2005 @ 5:31 pm
测试自动转向
December 27, 2005 @ 8:12 pm
测试自动跳转
December 29, 2005 @ 3:57 pm
思路很是好,小弟在下提几个建议:
一、“对象池”的管理功能须要增强,好比池的容量。
二、“对象池”的内存回收须要增强,好比使用完毕的对象释放内存。
三、请求最好序列一下,以控制因为服务器延时或网络延时致使的先请求的后获得结果。
四、为了代码复用和健壮,回调函数应该验证是否有效,也就是回调函数应该能够为空(能够缺省)。
December 31, 2005 @ 9:57 am
谢谢“野马”的建议,有空再完善一下。IE默认有两个线程的限制,因此池的容量不须要很大。
December 31, 2005 @ 1:11 pm
看 了legend的代码,才知道啥叫高手。很想请教legend,这些mozilla和ie各自特性和差异的资料从何处得来?由于我花了2个多钟头才查到 push和pop是ie5.5之后才有的;javascript中对象的构造O={:,:,:…}是javascript1.2里面就有的(所以这样写而 不是用new object()或者function objectname(){}应该具备更好的兼容性);以及那个颇有意思的addeventlistener是mozilla的DOM里面特有的。查到这 些东东,个人文件夹里面已经堆满了dom,javascript的相关规范了,并且仍是E文的,这多少让我有些灰心。还有几个问题,那个load是否是 mozilla里面xmlhttprequest的事件?load对应readystate=4,那么还有没有0,1,2,3对应的其余事件?由于我在 www.xmlhttp.cn上面没有找到这个信息,xmlhttprequest我在mozilla的DOM文档里面也没有找到。另外,那个“IE默认 有两个线程的限制,因此池的容量不须要很大”这句不太明白。
感谢你的这些文章和代码,若是可以解答个人这些疑问的话,就更感谢了,呵呵。
敬佩!
December 31, 2005 @ 2:09 pm
PS, “Content-Type=application/x-www-form-urlencoded; charset=UTF-8″是给服务器看的,xmlhttprequest并不会所以去编码data中的数据,所以data被send以前,须要手工编 码。我在IE下面用post试了一下,本身构造了一个form表单在http请求中的形式name1=value1&name2=value2, 若是不事先编码的话,value中若是有“?”或者汉字之类的字符,就会致使出错。对于get也有相似的问题。IE下面有encodeURI等几个函数用 来对字符串编码,能够解决这个问题,但这须要浏览器版本IE5.5以上(尽管encodeURI系列是ECMAScript标准)。我找到了一个能够进行 url编码的脚本,但仅仅是那个unicode和gb2312的对应数组,就一百多K。
想请教legend,是否有比较好的通用的解决方法?谢谢。
December 31, 2005 @ 2:52 pm
回 答hzy:一些浏览器方面的差异是我在之前作东西的时候遇到的,因此后面写代码的时候能够去避免这些问题。addeventlistener这个是参考 webfx上的一些代码。至于mozilla中xmlhttprequest里的事件,新版本中已经不存在这样的问题了,老版本未测试。
IE默认同时向一个站点发起的请求是两个,这个问题是我在作上传程序的时候遇到的,由于我同时向服务器发送三个请求,但最后一个一直得不到回应,只有等到前面两个结束后才能返回结果来。
至于urlencode这个在js里面用encodeURIComponent这个函数,各类浏览器均可以的。“Content-Type= application/x-www-form-urlencoded; charset=UTF-8"这句话是告诉服务器,我发送的数据是urlencode过的。
December 31, 2005 @ 3:32 pm
encodeURIComponent 在IE5.0里面没有,文档上这么说的,我没试过,因此结论下得比较武断。谢谢你耐心细致的解答。另外再跟你套个近乎,俺也是山东的。山东济南人。呵呵。 如今在青岛读研,也是26岁。呵呵。刚才好好看了你的blog一下发现了不少好东东,那个bindow,里面的图表功能颇有意思,不过估计只能在IE下面 运行(vml)?
今天很高兴,知道我有一个这么厉害的老乡。赞一个!
January 12, 2006 @ 12:04 pm
你好,原本想直接copy你的生成xmlhttp对象的代码,发现有点问题。
在IE下面也能够手工给window添加名为XmlHttpRequest的属性,若是用户代码中刚好有这么一个自定义的属性,这段代码就不能返回正确的对象了。也许就正如你所说,代码还有能够完善的地方。
PS,看你的代码有种很high的感受,自由而不放浪,英气逼人,呵呵。
January 16, 2006 @ 10:29 am
有一个问题,是否能够给每一个请求指定超时时间,加上超时处理?
January 17, 2006 @ 7:12 pm
很是感谢,你的东东帮了我很大的忙!
January 19, 2006 @ 8:29 pm
我想请教一个关于http://www.yule21.com/info/990.htm
这篇文章说得这个问题,他是用vbscript解决的
我想请问一下用javascript就必定没有办法解决了吗?
盼望答案
April 23, 2006 @ 7:50 pm
为何blog文章的标题不能复制呢?奇怪
April 29, 2006 @ 12:46 am
为何每次建立一个xmlHttprequest对象的代价须要考虑呢?即便浪费,不也是浪费clint端的那一点“小小”的性能么?对整个系统的性能会形成影响么?做者是否作过性能上的测试,或者有一些经验数据能够公布一下么?
May 10, 2006 @ 1:30 am
没有测试过也没有经验数据,只是认为ie每次建立activex对象应该是有些花销的。我这篇文章的主要目的并非为了节能,而是为了并发。
May 10, 2006 @ 1:59 am
??不建立一个池,就不能并发了么?
还有,xmlhttprequest对象的生命周期有多长?每次从池中取出一个用就能够么?
很差意思,新手,不明白的太多,呵呵。
May 10, 2006 @ 2:06 am
不建立也能够并发,但每次得建立一个新的xmlhttprequest对象。我建立池的目的,就是为了可以重复利用已经建立的对象。
说到并发,ie默认是每一个站点同时只容许两个线程的。
这篇文章如今看来,仍是有不少不妥的地方。
May 12, 2006 @ 7:34 pm
真高手,向你学习,顶一个。
May 17, 2006 @ 3:12 am
这东西不错。那个IE的Ajax缓存状况之前我遇到过,弄了我很久,到后来才发现IE的ajax会缓存。要是早看到你这篇文章就行了
June 6, 2006 @ 7:22 am
必定要说声感谢!
November 5, 2006 @ 5:43 pm
用你的代码在本地运行的时候就出现了状态代码是4 的时候回调函数没反应的状况,这个是怎么回事?
November 5, 2006 @ 8:08 pm
o~~ 试验成功了,以前不知道是哪里搞错了,多谢多谢,救急了
December 13, 2006 @ 3:05 pm
很是感谢
December 31, 2006 @ 11:31 am
思 路很好,不过有个问题,IE 解释脚本的时候是顺序执行的,这就是说,他会沿你设计的脚本一步一步走下去! 而 xmlhttpRequst 则是个异步过程,这样,当下一步脚本调用前,xmlhttpResquest 老是尚未send,因此这个线程池最后也没起到做用,调用1次sendReq就多建立一个xmlHttpRequest,和没用池子几乎没什么差异
December 31, 2006 @ 1:02 pm
調用xmlhttprequest就發送了,然後下一次調用的時候,若是前面的都在使用中,會自動創建一個新xmlhttp對象。若是有空閒的對象才會直接使用它。
這個池子並不是爲了效率,而是若是是單一的xmlhttprequest對象,重復調用的話,若是前一個正在發送,後面的就會覆蓋這個對象,那我們的請求就丟失了。
January 12, 2007 @ 3:03 am
谢谢您,您给了很大帮助。
April 21, 2007 @ 6:55 pm
使用中发现了一个问题。当我读取A完毕,并正确显示以后,点B,读取B的内容的时候,B能够正确显示,而A又会从新进入读取状态,并且始终没法完成,即staut始终=0。这是什么呢?怎么解决?
April 21, 2007 @ 6:59 pm
我代码作过改动。改动以下:(注:showid是传入的值,每次都不同,就是显示的地方。)
onreadystatechange = function ()
{
if (objXMLHttp.readyState “;
}
if (objXMLHttp.readyState == 4 && (objXMLHttp.status == 200 || objXMLHttp.status == 304))
{
var response = objXMLHttp.responseText;
document.getElementById(showid).innerHTML=response;
April 21, 2007 @ 8:28 pm
要不你就用这个吧: http://www.ugia.cn/?p=122
May 5, 2007 @ 3:58 pm
objXMLHttp.readyState = 0;
在ff中这样为对象添加一个属性能够吗?不是应该用addAttribute吗?
May 12, 2007 @ 12:08 pm
加入随机数怎么仍是没有办法解决IE的缓存
我用
xmlHttp.abort();
解决了
May 22, 2007 @ 9:08 am
???10)uuu(0)iii(0)ooo(0)000(0)0i(0)0889(0)45677(0)0gk(0)hh(0)u(0)p(0);(0)
ie下 请求页面获得的数据会出现如上的乱码 致使页面布局都乱了 请问这是怎么回事啊 xmlhttp.js里的中文注释我已经去掉了
ff下一切正常
May 22, 2007 @ 9:19 am
你页面 编码是什么?
May 22, 2007 @ 9:26 am
html:
New Document
js:
setRequestHeader(’Content-Type’, ‘application/x-www-form-urlencoded; charset=gb2312′);
send(data);
onreadystatechange = function ()
{
if (objXMLHttp.readyState == 4 && (objXMLHttp.status == 200 || objXMLHttp.status == 304))
{
//callback(objXMLHttp);
alert(objXMLHttp.responseText);
}
}
server端:asp
May 22, 2007 @ 9:27 am
server端:asp
May 22, 2007 @ 9:28 am
啊 不让发代码啊
server端 asp:
response.charset = “gb2312″
…
May 22, 2007 @ 9:30 am
客户端只是发送了一个请求页面 还没参数
var u2 = “txlload/load_team_list.asp”;
XMLHttp.sendReq(’GET’,u2,'’,callback); //打开页面时 加载分组
May 22, 2007 @ 9:48 am
问题找到了 是建立的xmlhttprequest对象问题
我改为这样了:
if(window.XMLHttpRequest){
objXMLHttp = new XMLHttpRequest();
if (objXMLHttp.overrideMimeType) {
objXMLHttp.overrideMimeType(”text/xml”);
}
}
else if (window.ActiveXObject){
try {
objXMLHttp = new ActiveXObject(”Msxml2.XMLHTTP”);
} catch (e) {
try {
objXMLHttp = new ActiveXObject(”Microsoft.XMLHTTP”);
} catch (e) {}
}
}
if (!objXMLHttp) {
window.alert(”can’t create XMLHttpRequest object.”);
return null;
}
ie下也正常了 不过不知道是什么缘由形成的
August 31, 2007 @ 10:40 am
我比较支持用json,由于rpc有性能问题
做者能告诉一下我QQ和MSN吗?
UGiA PHP UPLOADER 怎么实现远程上传?我意思是说我网站在A服务器,在A服务器页面上操做时,怎么把文件上传到B服务器上!
August 31, 2007 @ 10:42 am
上面发错地方了,应该发在 phprpc 那个里面
August 31, 2007 @ 10:52 am
写得真好,正想研究下并发的xhr呢,学习了,文档注释也很全,可贵啊!
October 24, 2007 @ 8:34 pm
能还能逐行的解释一下。
刚刚接触xmlhttprequest这方面的知识。
切盼
个人email:micenote@yahoo.com.cn
December 12, 2007 @ 2:17 pm
正好遇到这种问题,须要解决。这个方法很好用!
December 28, 2007 @ 12:33 am
其實在IE7.0 里面。
if (window.XMLHttpRequest)
{
var objXMLHttp = new XMLHttpRequest();
}
若是把 var objXMLHttp = new XMLHttpRequest();
//var objXMLHttp=new ActiveXObject(”Microsoft.XMLhttp”); 也是可行的。就是說。在IE7.0 里面。你先創建那個他就用那個。還有一個問題。就是當我們創建的是var objXMLHttp=new ActiveXObject(”Microsoft.XMLhttp”); 這個時候。responseText 這個東西能够用responsetext 就是說大小寫均可以的。可是若是是var objXMLHttp = new XMLHttpRequest(); 就必須是responseText。。。。 今天我就是給這個搞了好長時間。郁悶死了。