Для чего нужен setImmediate() в JavaScript и как он работает
Что проверяют
Понимаете ли вы устройство цикла событий Node.js, а не только то, что «колбэк выполнится потом». Почти всегда следом просят расставить порядок вывода для кода с setTimeout(fn, 0), setImmediate, process.nextTick и Promise.then.
Как отвечать
setImmediate() это API Node.js, а не часть стандарта JavaScript: в браузерах его нет. Он ставит колбэк в фазу check цикла событий libuv. Фазы идут по кругу: timers, pending callbacks, poll (ожидание и обработка ввода-вывода), check, close callbacks. Отсюда поведение:
- после ввода-вывода: колбэк выполняется сразу после фазы poll текущей итерации, не дожидаясь таймеров;
- внутри I/O-колбэка:
setImmediateгарантированно сработает раньшеsetTimeout(fn, 0). В основном модуле их порядок не определён, он зависит от того, успел ли истечь таймер в 1 мс; process.nextTickи промисы: это не фазы цикла, а очереди, которые разбираются после каждого колбэка. Сначала вся очередьnextTick, потом микрозадачи промисов, и только потом цикл идёт дальше;- голодание: рекурсивный
nextTickблокирует ввод-вывод, аsetImmediate, поставленный изнутри фазы check, уходит на следующую итерацию и даёт пройти запросам.
Главное применение: разбить долгую синхронную обработку на порции, чтобы сервер между ними успевал отвечать другим клиентам. Есть и промисная версия, setImmediate из node:timers/promises, её удобно ждать через await внутри цикла. Отменяется вызов через clearImmediate().
Где спотыкаются
Называют setImmediate способом распараллелить вычисления. Всё выполняется в том же потоке, для по-настоящему тяжёлой работы на CPU нужны worker_threads.
Говорят, что setImmediate выполняется «после всех операций ввода-вывода». Он выполняется после фазы poll текущей итерации, а новые события будут обработаны уже в следующей.
Уверенно утверждают, что setTimeout(fn, 0) всегда срабатывает раньше или всегда позже setImmediate. Ответ зависит от того, откуда вызван код.