8

我正在开发一个 Web 应用程序,该应用程序旨在显示一组使用 AJAX 定期更新的数据。一般的使用场景是用户整天打开它,不时看一眼。

我遇到了一个问题,即浏览器内存占用随着时间的推移缓慢增长。这发生在 Firefox 和 IE 7 中(虽然不在 Chrome 中)。几个小时后,它会导致 IE7 的占用空间约为 200MB,而 FF3 的占用空间约为 400MB。

经过大量测试,我发现只有在响应 AJAX 调用时才会发生内存泄漏。如果服务器没有响应任何东西,我可以让页面打开几个小时,并且占用空间不会增加。

我正在为我的 AJAX 调用使用原型。所以,我猜想创建这些内存泄漏的 onSuccess 回调存在问题。

有没有人有任何关于使用原型/AJAX 防止内存泄漏的提示?或有关如何解决此问题的任何方法?

编辑:发现问题出在我正在使用的 js 图形库中。可以在这里看到。

4

2 回答 2

11

您可以注意的最重要的事情是事件,以及您如何分配它们。

例如,采取这种情况(因为您没有提供一个):

<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时,您将拥有两倍的事件处理程序,并且垃圾收集无法删除第一组。

避免这种情况的一种方法是使用事件委托:

<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 事件的工作方式,“click” on.someButtonClass也会触发 on #ajaxResponseTarget,并且 Prototype 使得确定哪个元素是事件的目标变得非常简单。没有事件分配给 #ajaxResponseTarget的元素,因此无法将其内容替换为内目标的孤立事件。

于 2008-11-09T16:59:35.657 回答
-2

我可能错了,但听起来您正在围绕响应对象创建闭包。每个响应对象都会不同,这会导致内存占用增加。

于 2008-11-09T16:43:47.920 回答