在用AJAX做實時監控程序時,一直被客戶端句柄數不斷增加這個問題所困擾。原以爲這是XMLHTTP對象在作怪,忽然發現還是自己編程習慣所至。特別是對於javascript這種需要藉助腳本解析器的弱類型編成語言。真是一個小小的疏忽能帶來嚴重的後果。
先看看普通的AJAX客戶段寫法
{
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自帶的垃圾處理函數
{
CollectGarbage();
}
則呈現一個有趣的現象,客戶端佔用的內存會回收,但是句柄數的問題仍然沒有改觀。
這個小問題困擾了我好久,一直都沒有解決。折騰了好久最後才發現是自己寫腳本的時候沒有注意,其實稍作規範,這個問題就解決了。
在Requset函數中每一次新建xmlhttp對象前加上相當簡單的一行代碼
然後再定時調用Collect函數垃圾回收就什麼問題都沒有了。內存和句柄數都能及時地釋放。估計是腳本解析器中交叉引用後引用計數無法清零所致。
一直很奇怪,作爲一個比較成熟的ajax框架,ajax.net爲什麼沒有注意到客戶端句柄數問題。雖然看似一次兩次問題每什麼,但請求多了怎麼辦呢?ajax框架中新建請求對象的代碼如下
{
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 request = null;
try
{
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch(e)
{
try
{
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch(ee)
{}
}
return request;
}
中做了上述的處理,但實際問題並沒有解決,因爲在ajax_create_request中存在着這樣的代碼
也就是說在使用了一個XML文件獲取數據後並沒有即時釋放文件的句柄。修改如下就可以了
{
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];
}
現在覺得通用性太好沒有什麼實際的意義,方言性的和本項目,或者說滿足自己的需要最重要。不管怎麼說,還是自己的編程習慣有問題,很多細節的問題沒有注意。哎!吃一礆長一智吧!