Повышение производительности Ajax при длительном опросе

StackOverflow https://stackoverflow.com/questions/2094824

Вопрос

Я пишу веб-приложение (Только для Firefox-совместимый), который использует длительный опрос (с помощью возможностей ajax jQuery) для отправки более или менее постоянных обновлений с сервера клиенту.Я обеспокоен последствиями того, что это будет работать в течение длительного периода времени, скажем, весь день или ночь.Основной скелет кода таков:

function processResults(xml)
{
    // do stuff with the xml from the server
}

function fetch()
{
    setTimeout(function ()
    {
        $.ajax({
            type: 'GET',
            url: 'foo/bar/baz',
            dataType: 'xml',
            success: function (xml)
            {
                processResults(xml);
                fetch();
            },
            error: function (xhr, type, exception)
            {
                if (xhr.status === 0)
                {
                console.log('XMLHttpRequest cancelled');
                }
                else
                {
                    console.debug(xhr);
                    fetch();
                }
            }
        });
    }, 500);
}

(Полусекундный "спящий режим" предназначен для того, чтобы клиент не загружал сервер, если обновления возвращаются клиенту быстро - что обычно и происходит.)

После того, как эта функция была запущена на ночь, она, как правило, заставляет Firefox сканировать.Я думал, что это может быть частично вызвано большой глубиной стека, поскольку я в основном написал бесконечно рекурсивную функцию.Однако, если я использую Firebug и добавляю точку останова в fetch, похоже, что это не тот случай.Стек, который показывает мне Firebug, имеет глубину всего около 4 или 5 кадров, даже спустя час.

Одно из решений, которое я рассматриваю, - это замена моей рекурсивной функции на итеративную, но я не могу понять, как я мог бы вставить задержку между Ajax-запросами без вращения.Я просмотрел на Ключевое слово JS 1.7 "доходность" но я не могу до конца осознать это, чтобы понять, то ли это, что мне здесь нужно.

Является ли лучшим решением просто периодически выполнять жесткое обновление страницы, скажем, раз в час?Есть ли лучший / более компактный шаблон проектирования с длительным опросом, который не повредит браузеру даже после работы в течение 8 или 12 часов?Или я должен просто вообще пропустить длительный опрос и использовать другой шаблон "постоянное обновление", поскольку я обычно знаю, как часто сервер будет получать ответ для меня?

Это было полезно?

Решение

Также возможно, что это поджигатель.Вы находитесь в консоли.ведение журнала, что означает, что у вас, вероятно, открыта вкладка "Сетевой монитор" и т.д., Что означает, что каждый запрос сохраняется в памяти.

Попробуйте отключить его, посмотрите, поможет ли это.

Другие советы

Я подозреваю, что память утекает из processResults().

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

Ваш стек не должен быть глубоким, потому что fetch() возвращается немедленно.У вас нет бесконечно рекурсивного цикла.

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

Глубина стопки 4-5 - это правильно. setTimeout и $.ajax это асинхронные вызовы, которые возвращаются немедленно.Обратный вызов позже вызывается браузером с пустым стеком вызовов.Поскольку вы не можете реализовать длительный опрос синхронным способом, вы должны использовать этот рекурсивный подход.Нет никакого способа сделать это итеративным.

Я подозреваю, что причина этого замедления в том, что в вашем коде произошла утечка памяти.Утечка может быть либо в $.ajax с помощью jQuery (очень маловероятно) или в вашем processResults звони.

Это плохая идея звонить fetch() изнутри самого метода.Рекурсивность лучше использовать, когда вы ожидаете, что в какой-то момент метод завершится и результаты начнут отправляться вызывающей стороне.Дело в том, что когда вы вызываете метод рекурсивно, он сохраняет вызывающий метод открытым и использующим память.Если у вас глубина всего 3-4 кадра, это потому, что jQuery или браузер каким-то образом "исправляют" то, что вы сделали.

Последние версии jquery поддерживают длительный опрос по умолчанию.Таким образом, вы можете быть уверены, что вы не полагаетесь на интеллект браузера для обработки вашего бесконечного рекурсивного вызова.При вызове $.ajax() метод вы могли бы использовать приведенный ниже код для выполнения длительного опроса в сочетании с безопасным ожиданием в 500 миллисекунд перед новым вызовом.

function myLongPoll(){
    setTimeout(function(){
        $.ajax({
            type:'POST',
            dataType: 'JSON',
            url: 'http://my.domain.com/action',
            data: {},
            cache: false,
            success:function(data){

                //do something with the result

            },
            complete: myLongPoll, 
            async : false,
            timeout: 5000
        });
   //Doesn't matter how long it took the ajax call, 1 milisec or 
   //5 seconds (timeout), the next call will only happen after 2 seconds
   }, 2000);

Таким образом, вы можете быть уверены, что $.ajax() вызов закрывается до начала следующего.Это может быть доказано путем добавления простого console.log() на предыдущем и еще одном после вашего $.ajax() звони.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top