zoukankan      html  css  js  c++  java
  • 简单构建一个xmlhttp对象池合理创建和使用xmlhttp对象

    在我的这篇旧文里曾经发布了一个简单的ajax操作类。我们发现,在旧文里创建xmlhttp对象的时候,每次都要new一个对象。而我们都知道new一个对象的开销是很大的。如果我们在客户端频繁使用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#里的异步处理回调方法,它们在原理上其实是相通的。 哈哈,现在终于想通了, 真是太骄傲,太有出息了,想到就兴奋!

  • 相关阅读:
    技巧和诀窍;在VS 2005里优化ASP.NET 2.0Web项目的Build性能
    [资源]Flex 中文帮助
    13 Awesome Javascript CSS Menus
    兼容FF\IE的事件获得方法
    MSVCR80D.dll not found解决方案
    [转]一种革命性的自绘菜单实现
    [ZZ]马化腾关于产品设计与用户体验的培训
    [ZZ]WatiN:在.NET中测试Web应用程序
    How to Recommender Systems?
    淘宝第三届D2在上海举办
  • 原文地址:https://www.cnblogs.com/jeffwongishandsome/p/1648145.html
Copyright © 2011-2022 走看看