Подтвердить что ты не робот

Что такое setTimeout, когда установлено значение 0 миллисекунд?

В JavaScript setTimeout(callback, delay) означает "вызов callback после delay миллисекунд". Но что, если delay 0? Должен ли он позвонить callback сразу?

Я запутался из-за того, что вижу, когда запускаю следующий код:

setTimeout(function() { 
    console.log('AAA');
}, 0); // Call this in 0 milliseconds 

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
for (i = 0; i < 1000; i++) {
    console.log('CCC'); 
}
for (i = 0; i < 1000; i++) {
    console.log('DDD'); 
}
for (i = 0; i < 1000; i++) {
    console.log('EEE'); 
}

Это приводит к записи на консоль следующих команд:

console_log

Я ожидал увидеть AAA, зарегистрированного намного раньше этого. Было время, чтобы выполнить 4000 других вызовов console.log перед функцией, которая должна была быть вызвана немедленно.

Может кто-нибудь объяснить, что делает setTimeout, когда для задержки установлено значение 0 миллисекунд?

4b9b3361

Ответ 1

Несколько полезных фактов могут помочь выяснить, что происходит:

  • JavaScript является однопоточным. Асинхронные обратные вызовы назначаются сообщению, помещенному в очередь сообщений.
  • Если в настоящий момент код не выполняется, цикл событий проверяет очередь сообщений, запрашивая следующее сообщение в строке, которая должна быть обработана (выполнена).
  • setTimeout добавляет сообщение (с предоставленным обратным вызовом) в конец этой очереди после истечения указанной задержки.

(Примечание: это означает, что задержка в вызове setTimeout не является верным, это минимальная задержка до того, как будет выполнен обратный вызов. Фактическое время зависит от того, сколько времени потребуется для обработки любых сообщений перед ним в очереди.)

Итак, что произойдет, если для задержки установлено значение 0? Новое сообщение добавляется в очередь немедленно и будет обработано, когда исполняемый код будет завершен, и все ранее добавленные сообщения будут обработаны.

Что происходит в вашем коде

При вызове setTimeout...

setTimeout(function() { 
    console.log('AAA');
}, 0);

... сообщение добавляется в очередь с указанным обратным вызовом. Остальная часть вашего кода...

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
// etc.

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

Обратный вызов только когда-либо выполняется после завершения текущего исполняемого кода, независимо от того, сколько времени он занимает.

Дальнейшее чтение

Подробнее о цикле событий см. в разделе