现在的位置: 首页 > 综合 > 正文

xmlHttp请求在IE6/IE7/Firefox中只成功执行一次之分析

2013年02月09日 ⁄ 综合 ⁄ 共 9106字 ⁄ 字号 评论关闭

        异步调用的问题是五花八门,说碰上就碰上,这次我遇到的麻烦就是这样,同样的异步请求,在IE6SP1中运行一点问题没有,在IE6SP2中只成功执行一次后,每次的结果都和第一次一样,随后又尝试IE7和Firefox,效果和IE6SP2一样,用Fiddler监视明明显示正确的请求和返回值,可就是最终执行的效果一点都没变化,相当郁闷。这样的结果自然就想到了肯定是缓存在作怪,但始终还是要查明到底是哪段代码引起缓存的,我把关注的焦点放在如下代码:
var xmlHttp = null;
function getXmlHttp(){
    if(window.XMLHttpRequest){
        xmlHttp = new XMLHttpRequest();
    }else if(window.ActiveXObject){
        var arrXmlHttpTypes = ['MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.3.0','Microsoft.XMLHTTP'];
        for(var i=0;i<arrXmlHttpTypes.length;i++){
            try{
                xmlHttp = new ActiveXObject(arrXmlHttpTypes[i]);
            }catch(ex){}
        }
    }
}

function getXmlDom(content){
    var _xmlDom = null;
    if (!window.DOMParser  && window.ActiveXObject){
        var arrXmlDomTypes = ['MSXML2.DOMDocument.6.0','MSXML2.DOMDocument.3.0','Microsoft.XMLDOM'];
        for(var i=0;i<arrXmlDomTypes.length;i++){
            try{
                _xmlDom = new ActiveXObject(arrXmlDomTypes[i]);
                _xmlDom.async = false;
                _xmlDom.loadXML(content);
//                _xmlDom.setProperty('SelectionLanguage', 'XPath');
            }catch(ex){}
        }
    }else{
            try{
                var domParser = new window.DOMParser();
                _xmlDom =  domParser.parseFromString(content, 'text/xml');
                Element.prototype.selectSingleNode=function(sXPath){
                    var oEvaluator = new XPathEvaluator();
                    var oResult = oEvaluator.evaluate(sXPath,this,null, XPathResult.FIRST_ORDERED_NODE_TYPE,null);
                    if(null != oResult){
                        return oResult.singleNodeValue;
                    }
                    return null;
                }
               
                Element.prototype.selectNodes = function(sXPath){
                    var oEvaluator = new XPathEvaluator();
                    var oResult = oEvaluator.evaluate(sXPath,this,null, XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
                    var aNodes = new Array();
                    if(null != oResult){
                        var oElement = oResult.iterateNext();
                        while(oElement){
                            aNodes.push(oElement);
                            oElement = oResult.iterateNext();
                        }
                    }
                    return aNodes;
                }
               
                Element.prototype.__defineGetter__("text",function(){ return this.textContent; });        }
        catch (ex)
        {
           
        }
    }
    return _xmlDom;
}              

function postRequest(url,parameters,callBack){
    if(xmlHttp !=null){
        xmlHttp.onreadystatechange = function(){
            if(xmlHttp.readyState == 4){
                if(xmlHttp.status == 200){
                    xmlDom = getXmlDom(xmlHttp.responseText);
                    if(xmlDom != null){
                        eval(callBack(xmlDom));
                    }
                }
            }
        }
        xmlHttp.open('Post',url,true);
        xmlHttp.setRequestHeader("Content-Length",parameters.length);
        xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        xmlHttp.send(parameters);
    }
}
getXmlHttp();

        仔细一看红色标注的代码,可不是这里有问题么,用了全局的xmlHttp对象,这一定就是缓存的根本原因了,也怪一开始自己太不认真了,写这么懒的代码。赶紧改一下.

function getXmlHttp(){
    
var _xmlHttp = null;
    
if(window.XMLHttpRequest){
        _xmlHttp 
= new XMLHttpRequest();
        
return _xmlHttp;
    }
else if(window.ActiveXObject){
        
var arrXmlHttpTypes = ['MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.3.0','Microsoft.XMLHTTP'];
        
for(var i=0;i<arrXmlHttpTypes.length;i++){
            
try{
                _xmlHttp 
= new ActiveXObject(arrXmlHttpTypes[i]);
                
return _xmlHttp;
            }
catch(ex){}
        }
    }
}

function getXmlDom(content){
    
var _xmlDom = null;
    
if (!window.DOMParser  && window.ActiveXObject){
        
var arrXmlDomTypes = ['MSXML2.DOMDocument.6.0','MSXML2.DOMDocument.3.0','Microsoft.XMLDOM'];
        
for(var i=0;i<arrXmlDomTypes.length;i++){
            
try{
                _xmlDom 
= new ActiveXObject(arrXmlDomTypes[i]);
                _xmlDom.async 
= false;
                _xmlDom.loadXML(content);
//                _xmlDom.setProperty('SelectionLanguage', 'XPath');
            }catch(ex){}
        }
    }
else
        try{
                var domParser = new window.DOMParser();
                _xmlDom 
=  domParser.parseFromString(content, 'text/xml');
                Element.prototype.selectSingleNode
=function(sXPath){
                    
var oEvaluator = new XPathEvaluator();
                    
var oResult = oEvaluator.evaluate(sXPath,this,null, XPathResult.FIRST_ORDERED_NODE_TYPE,null);
                    
if(null != oResult){
                        
return oResult.singleNodeValue;
                    }
                    
return null;
                }
                
                Element.prototype.selectNodes 
= function(sXPath){
                    
var oEvaluator = new XPathEvaluator();
                    
var oResult = oEvaluator.evaluate(sXPath,this,null, XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
                    
var aNodes = new Array();
                    
if(null != oResult){
                        
var oElement = oResult.iterateNext();
                        
while(oElement){
                            aNodes.push(oElement);
                            oElement 
= oResult.iterateNext();
                        }
                    }
                    
return aNodes;
                }
                
                Element.prototype.__defineGetter__(
"text",function(){ return this.textContent; });
        }
        
catch (ex) 
        {
            
        }
    }
    
return _xmlDom;
}               

function postRequest(url,parameters,callBack){
    
var xmlHttp = getXmlHttp();
    
if(xmlHttp !=null){
        xmlHttp.onreadystatechange 
= function(){
            
if(xmlHttp.readyState == 4){
                
if(xmlHttp.status == 200){
                    xmlDom 
= getXmlDom(xmlHttp.responseText);
                    
if(xmlDom != null){
                        eval(func(xmlDom));
                    }
                }
            }
        }
        xmlHttp.open(
'Post',url,true);
        xmlHttp.setRequestHeader(
"Content-Length",parameters.length);
        xmlHttp.setRequestHeader(
"Content-Type","appli也cation/x-www-form-urlencoded");
        xmlHttp.send(parameters);
    }
}

        最后在网上也搜索了一下关于这个问题的解决办法,有不少文章介绍了另一种办法,就是对异步调用的参数加上一个随机数,我想,这个办法也太不厚道了吧,另外有一点值得借鉴的就是使用JSON实例化xmlHttp,将属性和方法用键值对形式完全包装,从可读性和扩展性上说,绝对是个好主意。以后我也经常写写这样的例子。先放legend的版本如下,摘自(http://www.ugia.cn/?p=85),带对象池的封装:

/**
 * 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);
            }
        }
    }
};  

抱歉!评论已关闭.