← Назад к вопросам

В чем разница между setTimeout и setImmediate?

2.0 Middle🔥 181 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между setTimeout и setImmediate

setTimeout и setImmediate - это две функции для отложенного выполнения кода, но они работают по-разному и вписываются в Event Loop в разных местах.

Event Loop и очереди

JavaScript имеет несколько очередей для обработки кода:

┌─────────────────────────────┐
│     Synchronous Code        │ (выполняется сразу)
├─────────────────────────────┤
│  Microtasks (Promises)      │ (setInterval, .then())
├─────────────────────────────┤
│  setTimeout/setInterval     │ (timer phase)
├─────────────────────────────┤
│   setImmediate (Node.js)    │ (check phase)
├─────────────────────────────┤
│  Microtasks (после check)   │
└─────────────────────────────┘

setTimeout

setTimeout помещает функцию в очередь таймеров. Она выполнится:

  1. После истечения времени (минимум 1-4 мс)
  2. После выполнения всех микротасков
  3. В следующем цикле Event Loop
console.log("1. Start");

setTimeout(() => {
  console.log("4. setTimeout (через 0мс)");
}, 0);

Promise.resolve().then(() => {
  console.log("3. Promise.then");
});

console.log("2. End");

// Вывод:
// 1. Start
// 2. End
// 3. Promise.then
// 4. setTimeout (через 0мс)

Почему Promise.then выполнится раньше setTimeout?

  • Promises - это микротаски (выполняются в конце текущего цикла)
  • setTimeout - это макротаск (выполняется в следующем цикле)

setImmediate (Node.js)

setImmediate доступен только в Node.js (не в браузере!). Она выполняется в фазе "check" Event Loop:

console.log("1. Start");

setImmediate(() => {
  console.log("3. setImmediate");
});

setTimeout(() => {
  console.log("2. setTimeout");
}, 0);

console.log("End");

// Node.js вывод:
// 1. Start
// End
// 2. setTimeout (timer phase)
// 3. setImmediate (check phase)

Детальное объяснение: Event Loop фазы в Node.js

   ┌───────────────────────────────┐
┌─>│ Timers (setTimeout, setInterval)│
│  └──────────────┬──────────────┘
│                 │
│  ┌──────────────┴──────────────┐
│  │   Pending Callbacks         │
│  └──────────────┬──────────────┘
│                 │
│  ┌──────────────┴──────────────┐
│  │   Idle, Prepare            │
│  └──────────────┬──────────────┘
│                 │
│  ┌──────────────┴──────────────┐
│  │   Poll (I/O events)        │
│  └──────────────┬──────────────┘
│                 │
│  ┌──────────────┴──────────────┐
│  │   Check (setImmediate)     │
│  └──────────────┬──────────────┘
│                 │
│  ┌──────────────┴──────────────┐
│  │   Close Callbacks          │
│  └──────────────┬──────────────┘
│                 │
└─────────────────┘

Практический пример

// Node.js
setTimeout(() => {
  console.log("A: setTimeout");
}, 0);

setImmediate(() => {
  console.log("B: setImmediate");
});

Promise.resolve().then(() => {
  console.log("C: Promise");
});

console.log("D: sync");

// Вывод:
// D: sync
// C: Promise (микротаск, выполняется первым после синхронного кода)
// A: setTimeout (timer фаза)
// B: setImmediate (check фаза)

Интересный момент: контекст вызова

setTimeout(() => {
  console.log("setTimeout");
  setImmediate(() => {
    console.log("setImmediate в setTimeout");
  });
}, 0);

setImmediate(() => {
  console.log("setImmediate");
  setTimeout(() => {
    console.log("setTimeout в setImmediate");
  }, 0);
});

// Вывод в Node.js:
// setTimeout
// setImmediate
// setImmediate в setTimeout
// setTimeout в setImmediate

Почему в таком порядке?

  1. Timer фаза: первый setTimeout выполняется
  2. В нём вызывается setImmediate -> в очередь check фазы
  3. Check фаза: первый setImmediate выполняется
  4. В нём вызывается setTimeout -> в очередь timer фазы
  5. Timer фаза: второй setTimeout выполняется
  6. Check фаза: второй setImmediate выполняется

Таблица сравнения

ХарактеристикаsetTimeoutsetImmediate
ДоступностьВезде (браузер, Node)Только Node.js
Время выполненияПосле истечения (минимум 1мс)После poll фазы
Относительная скоростьМедленнееБыстрее (в Node.js)
Фаза Event LoopTimer phaseCheck phase
ОтменаclearTimeout()clearImmediate()

Почему это важно для производительности

// Плохо: setTimeout блокирует другие фазы Event Loop
function processHeavyTask() {
  setTimeout(() => {
    // Эта фаза ждёт время + микротаски
  }, 0);
}

// Хорошо: setImmediate выполнится быстрее (в Node.js)
function processHeavyTask() {
  setImmediate(() => {
    // Эта фаза выполнится после poll
  });
}

Браузер vs Node.js

В браузере setImmediate не существует!

// Браузер
console.log(typeof setImmediate); // undefined

// Node.js
console.log(typeof setImmediate); // function

В браузере для похожего результата используют:

  • MessageChannel
  • requestAnimationFrame
  • Promise микротаски
// Браузерная альтернатива для "setImmediate"
const { port1, port2 } = new MessageChannel();

port1.onmessage = () => {
  console.log("Выполнилось в check-подобной фазе");
};

setTimeout(() => {
  port2.postMessage(null);
}, 0);

Вывод

  • setTimeout - универсальное решение для отложенного выполнения (макротаск)
  • setImmediate - только в Node.js, выполняется после I/O (check фаза)
  • setImmediate быстрее в Node.js благодаря порядку фаз
  • Promises выполняются раньше обоих (микротаски)
  • В браузере setImmediate недоступен

Для практики: используй setTimeout для кроссбраузерности, setImmediate для Node.js оптимизации.