JS: понимание того, как alert () влияет на цикл событий браузера - PullRequest
16 голосов
/ 07 июня 2011

Я рассматриваю возможность добавления alert () к нашей функции assert для утилиты javascript.

Мы являемся приложением, насыщенным ajax, и то, как наша инфраструктура (Ext) реализует ajax, опрашивая ответ ajax с помощью setInterval вместо ожидания readystate == 4, заставляет выполнять все наши обратные вызовы ajaxв контексте стека setInterval - и исключение / утверждение выдает его обычно молча.

Как низкоуровневое предупреждение () влияет на цикл событий браузера?Окно сообщений по определению должно позволять прокачке цикла событий win32 (реагировать на кнопку mbox).Означает ли это, что будут запущены другие события браузера, такие как будущие setIntervals, генерируемые нашей платформой, события изменения размера и т. Д.?Может ли это вызвать у меня проблемы?

IIRC: вы можете использовать FF2 и FF3.5, чтобы увидеть разницу, о которой я говорю.

alert('1');
setTimeout(function(){alert('2');}, 10);
alert('3');

FF 3.5 показывает 1-3-2.FF2 [1] показывает 1-2 и 3 (2 и 3 сложены друг на друга одновременно).Мы можем реплицировать 1-2 и 3 в IE8 с помощью win32 mbox, запущенного также из activex, вместо предупреждения, которое вызвало у нас недовольство в тот день, и я хочу убедиться, что мы не пойдем по этому пути снова.

Может ли кто-нибудь указать мне на конкретные низкоуровневые ресурсы, которые объясняют это поведение, каково ожидаемое поведение здесь и что именно происходит на низком уровне, включая то, почему поведение изменилось в версиях FF?

[1] вы можете скопировать это на Spoon.net, но я не могу сейчас работать.Я только что перенес его в виртуальную машину с FF 2.0.0.20.

Ответы [ 2 ]

7 голосов
/ 09 июня 2011

Во-первых, таймеры в javascript не очень точны. Интервалы меньше 30 мс можно считать одинаковыми, а реализации могут отличаться. Не надейтесь на неявное упорядочение.

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

Возьмите этот пример:

var hello = document.getElementById('hello')

setTimeout(function(){
  hello.style.backgroundColor = 'lime'
}, 5000)

alert('Stop!')

setTimeout(function(){
  hello.innerHTML = 'collaborate'
}, 20)

setTimeout(function(){
  hello.innerHTML = 'listen'
}, 1000)

Есть два возможных результата:

  1. Вы закрываете окно предупреждения менее чем за 5 секунд. Следующие два таймера будут установлены и сработают с заданными интервалами. Вы можете видеть, что цикл обработки событий остановлен, потому что независимо от того, сколько времени вы ждете, чтобы закрыть предупреждение, «listen» всегда будет выполняться 1 с.

  2. У вас больше 5 секунд, чтобы закрыть предупреждение. Первый интервал (bgColor) будет пройден, поэтому он будет выполнен немедленно, после чего будут установлены и вызваны два таймера.

http://jsbin.com/iheyi4/edit

Что касается интервалов, когда цикл обработки событий останавливается, он также «останавливает время», поэтому в этом случае:

i = 0

setInterval(function(){
  document.getElementById('n').innerHTML = ++i
}, 1000)

setTimeout(function(){
  alert('stop')
}, 5500)

Независимо от того, сколько времени вам потребуется, чтобы закрыть предупреждение, следующее число всегда будет равно 6 - setInterval не будет срабатывать несколько раз.

http://jsbin.com/urizo6/edit

1 голос
/ 07 июня 2011

Мне не удалось воспроизвести случай 1-2 и 3, но здесь - это скрипка, которая может помочь вам отладить то, что происходит в разных браузерах.

...