Может кто-нибудь объяснить мне, почему при запуске программы под оповещениями я получаю всегда «aaa», а затем «bbb»? Я ожидал бы последовать шаги:Javascript событий огонь в неправильном порядке?
запуске программы
прогонов программы и получает SetTimeout линии. Он устанавливает таймер, и этот таймер будет запущен через 5 секунд с этого момента (не когда программа закончится). В очереди событий ничего не осталось
затем, до 5 секунд, я нажимаю документ. Поскольку программа занята и все еще работает в цикле, она будет возвращать вызов для этого события click в очереди событий. Это единственное событие в четной очереди на данный момент (ранее установленный таймер не был запущен)
Прошло 5 секунд, возможно, цикл по-прежнему работает, и таймер мы устанавливаем с помощью огней setTimeout. Это приводит к тому, что таймеры обращаются к «aaa()» в очередь событий в качестве второго обратного вызова события, которое должно выполняться прямо за событием клика, которое уже находится в очереди.
Так что, когда программа заканчивается, я ожидаю, что она сначала предупредит «bbb», когда это событие было запущено первым (нажмите до 5 секунд), а затем «aaa» (пожар события setTimeout), но я всегда получаю «aaa» », а затем« bbb », почему?
Не является ли очередь событий Сначала в FIFO (сначала в первом случае)? Это зависит от браузера? Почему это происходит?
function aaa() {
alert("aaa");
}
setTimeout(aaa, 5000);
document.onclick = function() {
alert("bbb");
}
for (i = 0; i < 1000000; i++) {
console.log(i);
}
JSFiddle здесь http://jsfiddle.net/sQvYG/1/
EDIT: Если я что-то (возможно, очень обидное) отсутствует, похоже, приведенный выше код делает очень похожую вещь, что объясняет Джон Resigs блог в деталях на http://ejohn.org/blog/how-javascript-timers-work/. Точно так же, начинается таймер, щелчок происходит и добавляется в очередь. Таймер запускается и добавляется в очередь. Выполнение завершается, и обработчик клика выполняется первым, и это то, чего я ожидал бы. Кто-нибудь может пролить свет на то, почему это не происходит в правильном порядке для меня?
EDIT: благодаря bfavaretto, который доставил принятый ответ и был достаточно любезен, чтобы подробно объяснить очереди, я понял, что нет никого, кроме нескольких «очередей задач», где размещаются события. Таким образом, 5 шагов я первоначально описанные выше, на самом деле это:
ШАГ 1. (это то же самое) я начинаю программу
ШАГ 2. (это те же) запускается программа и получает SetTimeout линии , Он устанавливает таймер, и этот таймер будет запущен через 5 секунд с этого момента (не когда программа закончится). Пока еще ничего не помещено в очередь событий.
Также я считаю, на данный момент ничего не помещается в очередь заданий только пока, как я нашел на MOZILLA Dev странице https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop это:
«Вызов SetTimeout добавит сообщение в очередь после того, как время, прошедшее в качестве второго аргумента «.
Я также проверил это в Chrome и кажется, что обратный вызов добавляется в очередь задач, когда его фактически запускают.
ШАГ 3.затем, до передачи 5 секунд, я нажимаю на документ. Поскольку программа занята и все еще работает в цикле, она будет включать обратный вызов для этого события click в одной из очередей задач, которые браузер предоставляет для такого типа событий (щелчок мыши, очередь задач ui). Это единственное событие в этой очереди задач на данный момент. Другие очереди задач, например. для тайм-аутов в настоящий момент пуст.
ШАГ 4. 5 секунд прошло, петля, вероятно, все еще работает и таймер, который мы установили с помощью setTimeout
пожаров. Это ставит таймеры callback «aaa()» в очередь задач, предоставляемую браузером специально для такого рода событий (таймаутов). Итак, теперь у нас есть одна очередь задач, связанная с пользовательскими взаимодействиями, и у нас есть один обратный вызов в ожидании (обратный вызов из нашего клика ранее в пункте 3). И у нас есть еще одна очередь задач, которая имеет дело с тайм-аутами, и у нас есть один обратный вызов и там. Это тот, у кого есть метод aaa()
, который был запущен только через 5 секунд.
ШАГ 5. Итак, когда заканчивается программа, у нас есть две очереди задач с одним обратным вызовом. Теперь, даже если клик поместился в очередь задач сначала , нет никакой гарантии, что эта очередь задач (которая является взаимодействием пользователя или что-то, что касается щелчков мыши) будет обработана в первую очередь. Это полностью зависит от реализации браузера, и это то, что давало мне головные боли, пока бфаваретто не объяснил это в своем ответе.
Итак, в этом примере я упомянул только о двух очередях задач, однако браузер может иметь другие. Когда программа работает и занята, каждый тип события помещается в очередь задач для своего типа. После завершения программы браузер решает, какие очереди задач обрабатывать, отбирает обратный вызов оттуда, выполняет, как только закончил, захватывает что-то из тех же или других задач и так далее. Таким образом, на самом деле нет способа узнать, какая очередность будет обработана следующим образом. Однако задачи в каждой конкретной очереди всегда обрабатываются.
Ooff .. это, кажется, имеет смысл сейчас, статья Резига дала мне общее представление о том, как дела обстоят, но, как оказалось, это гораздо больше, и, надеюсь, наконец-то я понял это правильно.
Что это для for (i = 0; i <1000000; i ++) { console.log (i); } без него скрипт отлично работает. –
@YussufS: Это свидетельствует о непонимании событий JS, что это такое. : P Ничего не происходит UIwise, пока скрипт не вернется. – cHao
Мой первоначальный ответ не отвечает на ваш обновленный вопрос. Я только что добавил новый, отдельный ответ об этом. Я решил не удалять свой предыдущий ответ, так как я считаю, что он разъясняет некоторые недоразумения из первой части вашего вопроса. – bfavaretto