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];
}

 

現在覺得通用性太好沒有什麼實際的意義,方言性的和本項目,或者說滿足自己的需要最重要。不管怎麼說,還是自己的編程習慣有問題,很多細節的問題沒有注意。哎!吃一礆長一智吧!

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