Предотвращение утечек памяти AJAX - PullRequest
7 голосов
/ 09 ноября 2008

Я работаю над веб-приложением, предназначенным для отображения группы данных, которые периодически обновляются с помощью AJAX. Сценарий общего использования будет состоять в том, что пользователь оставит его открытым весь день и посмотрит на него время от времени.

Я столкнулся с проблемой, когда объем памяти в браузерах постепенно увеличивается. Это происходит как в Firefox, так и в IE 7 (хотя не в Chrome). Через несколько часов это может привести к тому, что IE7 займет около 200 МБ, а FF3 - около 400 МБ.

После многих испытаний я обнаружил, что утечка памяти происходит только в случае ответа на вызовы AJAX. Если сервер не отвечает ни на что, я могу оставить страницу открытой на несколько часов, и площадь не будет расти.

Я использую прототип для своих вызовов AJAX. Итак, я предполагаю, что есть проблема с обратным вызовом onSuccess, создающим эти утечки памяти.

У кого-нибудь есть советы по предотвращению утечек памяти с помощью прототипа / AJAX? Или какие-либо методы для устранения этой проблемы?

РЕДАКТИРОВАТЬ: обнаружил, что проблема заключается в библиотеке графиков js, которую я использую. Здесь можно увидеть .

Ответы [ 2 ]

10 голосов
/ 09 ноября 2008

Самое большое, на что вы можете обратить внимание - это события и то, как вы их назначаете.

Например, возьмите этот сценарий (поскольку вы его не предоставили):

<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, «щелчок» на .someButtonClass будет срабатывать также на #ajaxResponseTarget, а Prototype упрощает определение того, какой элемент был целью события. Элементам в #ajaxResponseTarget не присваиваются события, поэтому невозможно заменить его содержимое потерянными событиями из целей в пределах.

0 голосов
/ 09 ноября 2008

Возможно, я ошибаюсь, но похоже, что вы создаете замыкания вокруг объекта ответа. Каждый объект ответа будет отличаться, что приведет к увеличению объема памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...