Можно ли влиять на порядок выполнения задач в event loop
Что проверяют
Понимаете ли вы, что порядок в event loop не случайный, а определяется очередью, в которую попала задача, и умеете ли этим пользоваться, например чтобы не блокировать отрисовку. Следом почти всегда дают задачку «в каком порядке выведется» и спрашивают про requestAnimationFrame.
Как отвечать
Сам алгоритм цикла поменять нельзя, но вы выбираете, куда поставить работу, и этим управляете порядком. В браузере он такой:
- синхронный код: выполняется до конца текущей задачи, его ничто не прерывает;
- микрозадачи:
Promise.then, продолжение послеawait,queueMicrotask,MutationObserver. Очередь опустошается целиком после каждой задачи, до отрисовки; requestAnimationFrame: перед следующим кадром, место для изменений DOM и стилей, которые должны попасть в ближайший кадр;- задачи (макрозадачи):
setTimeout,setInterval, события,MessageChannel. По одной за оборот цикла; requestIdleCallback: когда браузеру нечем заняться, для некритичной работы.
Отдельный инструмент: Prioritized Task Scheduling API. scheduler.postTask(cb, { priority: "background" }) с приоритетами user-blocking, user-visible, background и scheduler.yield() для разбиения долгой задачи. Поддержка пока не во всех браузерах, нужна проверка наличия и запасной путь через setTimeout.
Практический смысл: длинную синхронную работу режут на куски и отдают управление между ними. Задача дольше 50 мс считается долгой и ухудшает INP. В Node порядок свой: process.nextTick раньше промисов, setImmediate идёт в фазе check после ввода-вывода.
Где спотыкаются
Считают, что setTimeout(fn, 0) выполнится сразу. Он встанет после всех микрозадач, а при глубокой вложенности таймеров браузер поднимает минимальную задержку до 4 мс.
Думают, что Promise.resolve().then() откладывает код «после всех событий». Он выполнится сразу после текущего стека, раньше отрисовки и любых таймеров.
Бесконечно ставят микрозадачи из микрозадач. Очередь не отпускает цикл, страница перестаёт рисоваться и отвечать на клики.