Вопрос проверяет понимание причин задержек таймеров: блокировка потока, приоритеты очередей и ограничения браузера.
setTimeout может выполниться позже, потому что после истечения времени callback попадает в очередь задач и ждёт своей очереди. Если основной поток занят синхронным кодом, выполнение откладывается. Также задержку увеличивают microtask, рендер и обработка событий. В фоне браузер может специально замедлять таймеры. Поэтому задержка может стать заметно больше, чем указанное значение.
Даже если таймер “истёк”, выполнение callback зависит от того, когда Event Loop сможет реально выполнить задачу.
Блокировка основного потока (call stack занят)
длинные циклы
тяжёлые вычисления
синхронные операции, которые долго выполняются
Очередь microtask имеет приоритет
после каждого завершения задачи Event Loop сначала выполняет microtask
большое количество Promise.then может “отодвигать” macrotask
Нагрузка: много задач в очереди macrotask
множество таймеров
обработчики событий
другие callbacks, которые накопились
Рендер и работа браузера
браузер может вставлять этапы отрисовки
тяжёлая разметка/стили/paint могут влиять на задержки
Ограничения браузера (throttling)
в неактивных вкладках таймеры часто “тормозятся”
экономия батареи и ресурсов
таймеры не подходят для точной синхронизации
если важна точность, нужно:
измерять реальное время через Date.now() / performance.now()
учитывать drift и корректировать расписание
Вывод:setTimeout выполняется позже из-за занятости call stack, приоритета microtask, нагрузки на очередь и ограничений браузера — это нормальное поведение Event Loop.