Возможно ли зацикливание событий в JavaScript с использованием document.dispatchEvent? - PullRequest
1 голос
/ 23 июня 2010

Я хотел бы создать механизм цикла событий в JavaScript / DOM, используя только вызовы dispatchEvent.

Например:

document.addEventListener("LoopingEvent", loop, true);
var loop = function() {
    doSomeWork();
    updateUI();
    document.dispatchEvent(loopEvent);
};
var loopEvent = document.createEvent('Events');
loopEvent.initEvent("LoopingEvent", true, true);
document.dispatchEvent(loopEvent);

При запуске возникает ошибка OutOfRange стека вызовов.Если я изменю диспетчерский вызов обработчика цикла на использование задержки window.setTimeout, он зацикливается без ошибки.

Просто интересно, есть ли способ использовать цикл dispatchEvent бесконечно, не прибегая к setInterval или setTimeout?Преимущество в циклическом шаблоне dispatchEvent заключается в том, что вызовы происходят, когда работа выполняется, а не через заданные интервалы времени.

Заранее спасибо за любые идеи ...

Ответы [ 3 ]

1 голос
/ 23 июня 2010

dispatchEvent отправляет событие синхронно с целью, поэтому при использовании dispatchEvent кадры обработчика событий накапливаются в стеке и в конечном итоге переполняются.

Если вы хотите просто «зацикливаться навсегда», вы имеетенесколько вариантов.Какой выбор правильный, зависит от того, как вы хотите, чтобы ваш код взаимодействовал с другими событиями.Я заметил, что ваш код предполагает, что он будет updateUI().Что ж, ваш обработчик событий должен периодически возвращаться в цикл событий браузера, чтобы он мог рисовать ваш обновленный интерфейс.Использование setTimeout(loop, 0); является хорошим способом для достижения этой цели:

function loop() {
  doSomeWork();
  updateUI();
  setTimeout(loop, 0);
}
loop();  // get things started

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

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

Если вы хотите, чтобы ваш цикл остановился, не вызывайте setTimeout, и он больше не будет вызываться.

Теперь здесьЭто альтернативный метод:

Если вы используете относительно свежую версию Firefox, Chrome или Safari, вы можете использовать новую функцию, называемую работники, для запуска цикла.Рабочие имеют свой собственный цикл обработки событий, поэтому можно писать код следующим образом:

// worker code
while (true) {
  doSomeWork();
  // post messages to update the UI
}

Рабочие работают отдельно от других сценариев;чтобы поместить результаты на саму страницу, вам нужно использовать функцию с именем postMessage.Вот соответствующая спецификация, , однако вы также можете поискать учебники или опубликовать дополнительный вопрос, потому что сначала отработать спецификацию может быть сложно.

0 голосов
/ 23 июня 2010

Я не могу комментировать dispatchEvent (), но что не так с этим шаблоном:

function DoSomeWork()
{
   // do work
   if (moreWorkNeedsDoing)
   {
      setTimeout(DoSomeWork, 0);
   }
}

Функция будет повторять «немедленно», пока есть работа.

0 голосов
/ 23 июня 2010

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

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

setTimeout с задержкой в ​​0 мсек приведет к такому эффекту, хотя зацикливание setTimeout или setInterval приведет к созданию еще одного бесконечного цикла, поэтому по крайней мере некоторая задержка необходима, так как яуказал выше.

...