Как мы знаем, событие l oop выглядит так:
timers -> IO -> poll -> check ->close -> timers -> ...
Таймеры: обратные вызовы из setInterval или setTimeout. Обратные вызовы ввода-вывода: обратные вызовы из событий ввода-вывода. Фазы опроса Опрос: получение новых событий ввода-вывода Проверка: здесь выполняются обратные вызовы из setImmediate Close: обрабатываются закрытые соединения, такие как сокеты
В первом примере -
Мы видим, что setTimeout выполняется до того, как setImmediate потому что очередь таймера помещается перед check Queue .
Однако во втором случае -
Когда выполняется setTimeout, он запускает другой setTimeout и a setImmediate, поскольку очередь проверки помещается после очереди таймера , очередь проверки того же l oop выполняет setImmediate, но вложенный setTimeout назначается для следующий цикл .
Вот почему приведенный ниже код также можно использовать для регулярного запуска чего-то
let timerId = setTimeout(function tick() {
alert('tick');
timerId = setTimeout(tick, 2000); // (*)
}, 2000);
Он планирует следующий вызов, прямо в конце первого вызова, который в основном регистрирует вызов setTimeout для следующего l oop.