Время выполнения обратного вызова не соответствует ожидаемому в Chrome - PullRequest
0 голосов
/ 28 сентября 2018

В этом блоге объясняется, как работает JavaScript.Он описывает стек, цикл обработки событий, очередь вызовов и контекст веб-API.

Я попробовал следующий пример:

function main() {
  setTimeout( () => alert('World') , 1000 ); // don't dismiss this alert for about 5 seconds
  setTimeout( () => alert('Mars') , 5000 );
}

main();

Я ожидаю, что оба таймера будут работать параллельно.Как только я отклоняю первое предупреждение, следующее предупреждение приходит немедленно.Это поведение в Firefox и Edge.Но в Chrome второе оповещение приходит через 5 секунд после того, как первое оповещение отклонено.Не ожидается.

Это проблема с реализацией Chrome?Chrome пытается провести некоторую оптимизацию?

Версии: Firefox Quantum 61.0.1, Chrome 69.0.3497.100, Edge 42.17134.1.0

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Краткий ответ: не используйте alert это плохая практика.Используйте console.log

Вызовы, такие как setTimeout(), являются API DOM.Они не запускаются в главном стеке выполнения (LIFO).Вместо этого они помещаются в параллельный поток, где они запускаются;Давайте назовем это потоком DOM.

В этом случае (сначала setTimeout = t1) t1 помещается в поток DOM, за которым следует t2, и main() продолжает выполняться.Когда время ожидания t1, обратный вызов помещается в очередь событий;по истечении времени t2 его обратный вызов помещается в ту же очередь.

Обратные вызовы в очереди событий затем вынимаются по порядку и выполняются в основном потоке.Однако каждый из них может произойти только в те моментальные снимки времени, когда основной стек пуст и браузер не занят.setTimeout только гарантирует, что обратный вызов не будет вызываться ДО указанного времени.

Если бы вы использовали пользователь console.log вместо оповещения, вы бы увидели, что код выполняется должным образом.Использование оповещений является плохой практикой и фактически останавливает выполнение JS в Chrome (насколько я могу судить).

setTimeout с предупреждением и без него

0 голосов
/ 28 сентября 2018

Одна из особенностей JS заключается в том, что среды выполнения различаются, и вы, похоже, знакомы с различными доступными механизмами.

В Chrome alert - это метод блокировки, который останавливает выполнение.

Рассмотрим этот пример:

(() => {
  for (let i = 0; i < 10; i++) {
    setTimeout(() => console.log(i), i*1000)
  }
  setTimeout(() => alert('World'), 1000)
  setTimeout(() => alert('Mars'), 5000)
})()

Вы увидите, что счетчик останавливается и возобновляет работу после того, как предупреждение было отменено.Однако ваши ожидания верны, когда JS обычно считается non-blocking, и чаще всего такие методы, как setTimeout, будут запускаться асинхронно (например, в цикле for, где таймер должен быть увеличен для желаемого поведения).).

...