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