AJAX长时间轮循交互数据时客户端句柄数持续增加的解决方法

        在用AJAX做实时监控程序时,一直被客户端句柄数不断增加这个问题所困扰。原以为这是XMLHTTP对象在作怪,忽然发现还是自己编程习惯所至。特别是对于javascript这种需要借助脚本解析器的弱类型编成语言。真是一个小小的疏忽能带来严重的后果。

         先看看普通的AJAX客户段写法

 

function Request()
    

            
        
try {
          xmlhttp 
= new ActiveXObject("Msxml2.XMLHTTP");  //W3C标准
            }
 catch (e) {
             
try {
                xmlhttp 
= new ActiveXObject("Microsoft.XMLHTTP");   //微软标准
            }
 catch (e) {
            xmlhttp 
= false;
            }

         }

        
if (!xmlhttp && typeof XMLHttpRequest!='undefined'{
          xmlhttp 
= new XMLHttpRequest();
        }

        xmlhttp.onreadystatechange 
= ResponseContents;
        xmlhttp.open(
'POST', url, true);
        xmlhttp.SetRequestHeader (
"Content-Type","text/xml; charset=gb2312"); 
        xmlhttp.send(data);
    }

然后再加上回调处理函数就完成了一个简单的ajax调用

 

    //监听数据
    function ResponseContents()
    
{
        
if (xmlhttp.readyState==4)
        
{
             
if (xmlhttp.status==200)
             
{
                    div 
= document.getElementById("testDiv");
                    div.innerHTML 
= xmlhttp.responseText;                   
             }

             
else
             
{
                alert(
"XML文档错误: "+xmlhttp.statusText);
             }

        }

    }

在定时做请求的时候会发现,客户端IE的资源如占用内存,句柄数等都在持续的上升。如果请求频率比较高的话,占用资源就相当可怕。

如果调用javascript自带的垃圾处理函数

 

 function Collect()
    
{
       CollectGarbage();
    }

则呈现一个有趣的现象,客户端占用的内存会回收,但是句柄数的问题仍然没有改观。

        这个小问题困扰了我好久,一直都没有解决。折腾了好久最后才发现是自己写脚本的时候没有注意,其实稍作规范,这个问题就解决了。

在Requset函数中每一次新建xmlhttp对象前加上相当简单的一行代码

 

var xmlhttp = null;

然后再定时调用Collect函数垃圾回收就什么问题都没有了。内存和句柄数都能及时地释放。估计是脚本解析器中交叉引用后引用计数无法清零所致。

         一直很奇怪,作为一个比较成熟的ajax框架,ajax.net为什么没有注意到客户端句柄数问题。虽然看似一次两次问题每什么,但请求多了怎么办呢?ajax框架中新建请求对象的代码如下

 

function ajax_create_request(context)
{
    
for(var i=0; i<requests.length; i++)
    
{
        
if(requests[i].readyState == 4)
        
{
            requests[i].abort();
            requests[i].context 
= context;
            
return requests[i];
        }

    }


    
var pos = requests.length;
    
    requests[pos] 
= Object();
    requests[pos].obj 
= new XMLHttpRequest();
    requests[pos].context 
= context;
    
    
return requests[pos];
}

虽然XMLHttpRequest函数中

 

var XMLHttpRequest = function()
{
    
var request = null;
    
try
    
{
        request 
= new ActiveXObject('Msxml2.XMLHTTP');
    }

    
catch(e)
    
{
        
try
        
{
            request 
= new ActiveXObject('Microsoft.XMLHTTP');
        }

        
catch(ee)
        
{}
    }

    
return request;
}

中做了上述的处理,但实际问题并没有解决,因为在ajax_create_request中存在着这样的代码

 

requests[pos].obj = new XMLHttpRequest();

也就是说在使用了一个XML文件获取数据后并没有即时释放文件的句柄。修改如下就可以了

 

function ajax_create_request(context)
{
    
var pos = requests.length;
    
    
if(pos<10)
    
{
        
for(var i=0; i<pos; i++)
        
{
            
if(requests[i].readyState == 4)
            
{
                requests[i].abort();
                requests[i].context 
= context;
                
return requests[i];
            }

        }


    }

    
else
    
{
        
for(var i=0; i<pos; i++)
        
{
            
if(requests[i].readyState == 4)
            
{
                requests[i].abort();
            }

            requests[i].obj 
= null;
            requests[i]
=null;
        }

        requests
=new Array();
        pos
=0;
    }

    
    requests[pos] 
= Object();
    requests[pos].obj 
= new XMLHttpRequest();
    requests[pos].context 
= context;
    
    
return requests[pos];
}

 

现在觉得通用性太好没有什么实际的意义,方言性的和本项目,或者说满足自己的需要最重要。不管怎么说,还是自己的编程习惯有问题,很多细节的问题没有注意。哎!吃一硷长一智吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章