setTimeout против setImmediate против process.nextTick

В чем разница между setTimeout(callback, 0) а также process.nextTick(callback)? Как насчет узла setImmediate(callback)?

На первый взгляд кажется, что все три функции делают одно и то же — они выполняют обратный вызов после текущего цикла обработки событий, но до всего остального. Возникает естественный вопрос: почему существуют три разные функции? Проведем эксперимент:

let racer = function() {
  setTimeout(() => console.log("timeout"), 0);
  setImmediate(() => console.log("immediate"));
  process.nextTick(() => console.log("nextTick"));
  console.log("current event loop");
}

racer()

Из вывода видно, что эти обратные вызовы не выполняются в том же порядке, в котором они были написаны в исходном коде.

[Running] node "/Users/logicmason/timeouts.js"
current event loop
nextTick
timeout
immediate

[Done] exited with code=0 in 0.203 seconds

Объяснение

Первым казненным был process.nextTick, который помещает свой обратный вызов в начало очереди событий. Он будет выполняться после текущего кода, но перед любыми событиями ввода-вывода или таймерами.

Далее идет «тайм-аут». Поскольку мы прошли setTimeout тайм-аут равен 0, нет дополнительной принудительной задержки перед его выполнением, и он помещается в очередь таймера во время следующего цикла.

Наконец, у нас есть setImmediate, что явно не так быстро, как следует из его названия! Его обратный вызов помещается в очередь проверки следующего цикла цикла обработки событий. Поскольку очередь проверки возникает позже, чем очередь таймера, setImmediate будет медленнее, чем setTimeout 0.

В целом цикл событий выглядит так:

timers -> IO -> poll -> check ->close -> timers -> …

Таймеры: обратные вызовы от setInterval или же setTimeout
обратные вызовы ввода-вывода: обратные вызовы от событий ввода/вывода
Праздный: используется узлом внутри между фазами ввода-вывода и опроса.
Опрос: получить новые события ввода/вывода
Проверять: обратные вызовы от setImmediate выполнить здесь
Закрывать: обрабатывать закрытые соединения, такие как сокеты

Время вызова!

Что вы ожидаете от следующего кода в Node?

let racer1 = function() {
    setTimeout(() => console.log("timeout"), 0);
  setImmediate(() => console.log("immediate"));
  process.nextTick(() => console.log("nextTick"));
}

let racer2 = function() {
  process.nextTick(() => console.log("nextTick"));
    setTimeout(() => console.log("timeout"), 0);
  setImmediate(() => console.log("immediate"));
}

let racer3 = function() {
  setImmediate(() => console.log("immediate"));
  process.nextTick(() => console.log("nextTick"));
    setTimeout(() => console.log("timeout"), 0);
}

racer1()
racer2()
racer3()

Это было то, что вы ожидали?

Первоначально опубликовано на Logicmason.com

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *