转载 Xmlhttprequest对象池

 

 

在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

50 Comments &raquo;

  1. s5s5 said,

    December 22, 2005 @ 7:12 pm数组

    大哥哥,你的日志时间超前了吧,已经在BXNA显示了一天了。。。浏览器

  2. legend said,

    December 22, 2005 @ 7:19 pm缓存

    我发现这个问题了,后台的时间选项改了改,没管用,帖子时间我也改了。郁闷

    再改,改到21号

  3. danielking said,

    December 23, 2005 @ 9:12 am

    怎么在IE下使用有问题呢?
    提示64行第5个字符,缺乏标识符字符串或数字
    而后提示XMLHttp未定义

    在Firefox使用正常

  4. legend said,

    December 23, 2005 @ 9:39 am

    源代码里有中文的注释,是ansi的,若是你的网站或ie下选择编码为UTF-8,可能会致使错误,你把你ie的编码改为gb2312看看,或者去掉文件里的中文注释

  5. nickfan said,

    December 26, 2005 @ 10:48 am

    服务器是否是php5的?可能须要设置一下php.ini。

  6. andot said,

    December 27, 2005 @ 5:28 pm

    测试自动转向

  7. legend said,

    December 27, 2005 @ 5:31 pm

    测试自动转向

  8. andot said,

    December 27, 2005 @ 8:12 pm

    测试自动跳转

  9. 野马 said,

    December 29, 2005 @ 3:57 pm

    思路很是好,小弟在下提几个建议:
    一、“对象池”的管理功能须要增强,好比池的容量。
    二、“对象池”的内存回收须要增强,好比使用完毕的对象释放内存。
    三、请求最好序列一下,以控制因为服务器延时或网络延时致使的先请求的后获得结果。
    四、为了代码复用和健壮,回调函数应该验证是否有效,也就是回调函数应该能够为空(能够缺省)。

  10. legend said,

    December 31, 2005 @ 9:57 am

    谢谢“野马”的建议,有空再完善一下。IE默认有两个线程的限制,因此池的容量不须要很大。

  11. hzy said,

    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默认 有两个线程的限制,因此池的容量不须要很大”这句不太明白。
    感谢你的这些文章和代码,若是可以解答个人这些疑问的话,就更感谢了,呵呵。
    敬佩!

  12. hzy said,

    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,是否有比较好的通用的解决方法?谢谢。

  13. legend said,

    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过的。

  14. hzy said,

    December 31, 2005 @ 3:32 pm

    encodeURIComponent 在IE5.0里面没有,文档上这么说的,我没试过,因此结论下得比较武断。谢谢你耐心细致的解答。另外再跟你套个近乎,俺也是山东的。山东济南人。呵呵。 如今在青岛读研,也是26岁。呵呵。刚才好好看了你的blog一下发现了不少好东东,那个bindow,里面的图表功能颇有意思,不过估计只能在IE下面 运行(vml)?
    今天很高兴,知道我有一个这么厉害的老乡。赞一个!

  15. hzy said,

    January 12, 2006 @ 12:04 pm

    你好,原本想直接copy你的生成xmlhttp对象的代码,发现有点问题。
    在IE下面也能够手工给window添加名为XmlHttpRequest的属性,若是用户代码中刚好有这么一个自定义的属性,这段代码就不能返回正确的对象了。也许就正如你所说,代码还有能够完善的地方。
    PS,看你的代码有种很high的感受,自由而不放浪,英气逼人,呵呵。

  16. FindRain said,

    January 16, 2006 @ 10:29 am

    有一个问题,是否能够给每一个请求指定超时时间,加上超时处理?

  17. mincyw said,

    January 17, 2006 @ 7:12 pm

    很是感谢,你的东东帮了我很大的忙!

  18. maltose said,

    January 19, 2006 @ 8:29 pm

    我想请教一个关于http://www.yule21.com/info/990.htm
    这篇文章说得这个问题,他是用vbscript解决的
    我想请问一下用javascript就必定没有办法解决了吗?
    盼望答案

  19. longbill said,

    April 23, 2006 @ 7:50 pm

    为何blog文章的标题不能复制呢?奇怪

  20. Huangl said,

    April 29, 2006 @ 12:46 am

    为何每次建立一个xmlHttprequest对象的代价须要考虑呢?即便浪费,不也是浪费clint端的那一点“小小”的性能么?对整个系统的性能会形成影响么?做者是否作过性能上的测试,或者有一些经验数据能够公布一下么?

  21. legend said,

    May 10, 2006 @ 1:30 am

    没有测试过也没有经验数据,只是认为ie每次建立activex对象应该是有些花销的。我这篇文章的主要目的并非为了节能,而是为了并发。

  22. Huangl said,

    May 10, 2006 @ 1:59 am

    ??不建立一个池,就不能并发了么?
    还有,xmlhttprequest对象的生命周期有多长?每次从池中取出一个用就能够么?
    很差意思,新手,不明白的太多,呵呵。

  23. legend said,

    May 10, 2006 @ 2:06 am

    不建立也能够并发,但每次得建立一个新的xmlhttprequest对象。我建立池的目的,就是为了可以重复利用已经建立的对象。

    说到并发,ie默认是每一个站点同时只容许两个线程的。

    这篇文章如今看来,仍是有不少不妥的地方。

  24. nada said,

    May 12, 2006 @ 7:34 pm

    真高手,向你学习,顶一个。

  25. Zhang-Zi said,

    May 17, 2006 @ 3:12 am

    这东西不错。那个IE的Ajax缓存状况之前我遇到过,弄了我很久,到后来才发现IE的ajax会缓存。要是早看到你这篇文章就行了

  26. An said,

    June 6, 2006 @ 7:22 am

    必定要说声感谢!

  27. diaodiao said,

    November 5, 2006 @ 5:43 pm

    用你的代码在本地运行的时候就出现了状态代码是4 的时候回调函数没反应的状况,这个是怎么回事?

  28. diaodiao said,

    November 5, 2006 @ 8:08 pm

    o~~ 试验成功了,以前不知道是哪里搞错了,多谢多谢,救急了

  29. 海南马自达 said,

    December 13, 2006 @ 3:05 pm

    很是感谢

  30. Alan said,

    December 31, 2006 @ 11:31 am

    思 路很好,不过有个问题,IE 解释脚本的时候是顺序执行的,这就是说,他会沿你设计的脚本一步一步走下去! 而 xmlhttpRequst 则是个异步过程,这样,当下一步脚本调用前,xmlhttpResquest 老是尚未send,因此这个线程池最后也没起到做用,调用1次sendReq就多建立一个xmlHttpRequest,和没用池子几乎没什么差异

  31. legend said,

    December 31, 2006 @ 1:02 pm

    調用xmlhttprequest就發送了,然後下一次調用的時候,若是前面的都在使用中,會自動創建一個新xmlhttp對象。若是有空閒的對象才會直接使用它。

    這個池子並不是爲了效率,而是若是是單一的xmlhttprequest對象,重復調用的話,若是前一個正在發送,後面的就會覆蓋這個對象,那我們的請求就丟失了。

  32. streetsmart said,

    January 12, 2007 @ 3:03 am

    谢谢您,您给了很大帮助。

  33. kevin said,

    April 21, 2007 @ 6:55 pm

    使用中发现了一个问题。当我读取A完毕,并正确显示以后,点B,读取B的内容的时候,B能够正确显示,而A又会从新进入读取状态,并且始终没法完成,即staut始终=0。这是什么呢?怎么解决?

  34. kevin said,

    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;

  35. legend said,

    April 21, 2007 @ 8:28 pm

    要不你就用这个吧: http://www.ugia.cn/?p=122

  36. huxishengming said,

    May 5, 2007 @ 3:58 pm

    objXMLHttp.readyState = 0;
    在ff中这样为对象添加一个属性能够吗?不是应该用addAttribute吗?

  37. zeroone said,

    May 12, 2007 @ 12:08 pm

    加入随机数怎么仍是没有办法解决IE的缓存
    我用
    xmlHttp.abort();
    解决了

  38. 毛毛虫 said,

    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下一切正常

  39. legend said,

    May 22, 2007 @ 9:19 am

    你页面 编码是什么?

  40. 毛毛虫 said,

    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

  41. 毛毛虫 said,

    May 22, 2007 @ 9:27 am

    server端:asp

  42. 毛毛虫 said,

    May 22, 2007 @ 9:28 am

    啊 不让发代码啊
    server端 asp:
    response.charset = “gb2312″

  43. 毛毛虫 said,

    May 22, 2007 @ 9:30 am

    客户端只是发送了一个请求页面 还没参数
    var u2 = “txlload/load_team_list.asp”;
    XMLHttp.sendReq(’GET’,u2,'’,callback); //打开页面时 加载分组

  44. 毛毛虫 said,

    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下也正常了 不过不知道是什么缘由形成的

  45. Jeffy said,

    August 31, 2007 @ 10:40 am

    我比较支持用json,由于rpc有性能问题
    做者能告诉一下我QQ和MSN吗?
    UGiA PHP UPLOADER 怎么实现远程上传?我意思是说我网站在A服务器,在A服务器页面上操做时,怎么把文件上传到B服务器上!

  46. Jeffy said,

    August 31, 2007 @ 10:42 am

    上面发错地方了,应该发在 phprpc 那个里面

  47. hongyu said,

    August 31, 2007 @ 10:52 am

    写得真好,正想研究下并发的xhr呢,学习了,文档注释也很全,可贵啊!

  48. 胡杨 said,

    October 24, 2007 @ 8:34 pm

    能还能逐行的解释一下。
    刚刚接触xmlhttprequest这方面的知识。
    切盼
    个人email:micenote@yahoo.com.cn

  49. irene said,

    December 12, 2007 @ 2:17 pm

    正好遇到这种问题,须要解决。这个方法很好用!

  50. 破曉之陽 said,

    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。。。。 今天我就是給這個搞了好長時間。郁悶死了。

相关文章
相关标签/搜索