我正在设计一个Web应用程序,该应用程序旨在显示一堆使用AJAX定期更新的数据。一般的使用场景是用户将整天保持打开状态,然后不时浏览一下。
我遇到的问题是浏览器的内存占用量随时间缓慢增长。Firefox和IE 7(尽管不是Chrome)都在发生这种情况。几个小时后,它可能导致IE7占用约200MB的内存,而FF3导致占用约400MB的内存。
经过大量测试,我发现只有在响应AJAX调用时才会发生内存泄漏。如果服务器没有任何响应,我可以将页面保持打开状态数小时,并且占用空间不会增加。
我正在为AJAX调用使用原型。因此,我猜测onSuccess回调在创建这些内存泄漏时存在问题。
有没有人对使用原型/ AJAX防止内存泄漏有任何提示?或任何方法如何解决此问题?
编辑:发现问题出在我正在使用的js图形库中。可以在这里看到。
您可以注意的最大事件是事件及其分配方式。
例如,采用这种情况(因为您尚未提供):
<div id="ajaxResponseTarget"> ... </div> <script type="text/javascript"> $(someButton).observe('click', function() { new Ajax.Updater($('ajaxResponseTarget'), someUrl, { onSuccess: function() { $$('#ajaxResponseTarget .someButtonClass').invoke('observe', 'click', function() { ... }); } }); }); </script>
这将导致内存泄漏,因为在进行#ajaxResponseTarget更新时(内部,Prototype将使用innerHTML)带有click事件的元素将从文档中删除而不会删除其事件。第二次单击someButton,您将获得两倍的事件处理程序,并且垃圾回收无法删除第一组事件处理程序。
#ajaxResponseTarget
innerHTML
click
someButton
避免这种情况的一种方法是使用事件委托:
<div id="ajaxResponseTarget"> ... </div> <script type="text/javascript"> $('ajaxResponseTarget').observe('click', function(e) { if(e.element().match('.someButtonClass')) { ... } }); $(someButton).observe('click', function() { new Ajax.Updater($('ajaxResponseTarget'), someUrl); }); </script>
由于DOM事件的工作方式,.someButtonClass也会在上触发“ click” #ajaxResponseTarget,并且Prototype使确定事件目标的元素变得非常简单。没有事件被分配到元素 之内 #ajaxResponseTarget,所以也没有办法为内目标替换它的内容,以孤儿的活动。
.someButtonClass