Сможет ли рекурсивный вызов функции setTimeout в конечном итоге убить JS Engine? - PullRequest
13 голосов
/ 21 июля 2011

Допустим, у меня есть некоторые данные, которые мне нужно получать с сервера примерно каждые 10 секунд. Я хотел бы иметь функцию, которая получает данные через AJAX и затем вызывает setTimeout для повторного вызова этой функции:

function GetData(){
   $.ajax({
       url: "data.json",
       dataType: "json",
       success: function(data){
         // do somthing with the data

         setTimeout(GetData, 10000);
      },
      error: function(){
         setTimeout(GetData, 10000);
      }
   });
}

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

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

Каков наилучший способ обработки функции, которую необходимо периодически вызывать?

1 Ответ

23 голосов
/ 21 июля 2011

Реальной рекурсии нет, потому что вызов GetData задерживается, а контекст JavaScript тем временем разрушается.Так что это не приведет к сбою механизма JS.

Для вашего примера кода это в основном то, что произойдет на уровне механизма JS:

  1. Инициализация двигателя JS
  2. Создание контекста функции GetData
  3. Выполнение операторов GetData, включая «setTimeOut»
  4. «setTimeOut», инструктирует движку JS вызывать функцию за 10 секунд
  5. Уничтожить контекст функции GetData
  6. На данный момент, с точки зрения использования памяти, мы вернулись к шагу 1. Единственное отличие состоит в том, что механизм JS сохранил ссылку на функцию и когда ее вызывать (давайте назовем эти данные «futureCall»).
  7. Через 10 секунд повторите процедуру, начиная с шага 2. «futureCall» уничтожается.
...