2010-01-19 3 views
5

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

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 "yield" keyword, но я не могу обернуть вокруг себя голову, чтобы выяснить, нужно ли мне здесь.

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

ответ

2

Возможно также, что это FireBug. Вы - материал console.logging, что означает, что вы, вероятно, открываете вкладку сетевого монитора и т. Д., Что означает, что каждый запрос хранится в памяти.

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

+0

Это помогает мне! – JulienFr

2

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

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

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

Возможно, вы захотите использовать Firefox Leak Monitor Add-on, чтобы помочь вам в обнаружении утечек памяти.

+0

Я думал об этом как о другом способе «сломать» глубину стека, но я не вижу, что это имеет какой-то другой эффект от «setTimeout» в моем исходном коде. –

+0

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

+0

Я подозреваю, что ваша память просачивается из 'processResults()'. –

1

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

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

1

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

Последние выпуски поддержки jQuery для длительного опроса по умолчанию. Таким образом, вы можете быть уверены, что yhou не отвлекают внимание от интеллекта браузера, чтобы справиться с бесконечным рекурсивным вызовом. При вызове метода $.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().

+0

Использование jQuery 'complete' callback существенно не отличается от реализации в моем вопросе. Это не Java - абонентам никогда не нужно явно закрывать XHR или другие ресурсы. –