Понимание setImmediate()
Когда вы хотите выполнить фрагмент кода асинхронно, но как можно скорее, один из вариантов - использовать функцию setImmediate(), предоставляемую Node.js:
setImmediate(() => {
// сделать что-то
})Любая функция, переданная в качестве аргумента setImmediate(), является обратным вызовом, который выполняется в следующей итерации цикла событий.
Чем setImmediate() отличается от setTimeout(() => {}, 0) (с передачей тайм-аута в 0 мс) и от process.nextTick() и Promise.then()?
Функция, переданная в process.nextTick(), будет выполнена в текущей итерации цикла событий, после завершения текущей операции. Это означает, что она всегда будет выполняться до setTimeout и setImmediate.
Обратный вызов setTimeout() с задержкой 0 мс очень похож на setImmediate(). Порядок выполнения будет зависеть от различных факторов, но оба они будут запущены в следующей итерации цикла событий.
Обратный вызов process.nextTick добавляется в очередь process.nextTick. Обратный вызов Promise.then() добавляется в очередь микрозадач promises. Обратный вызов setTimeout, setImmediate добавляется в очередь макрозадач.
Цикл событий сначала выполняет задачи в очереди process.nextTick, затем выполняет очередь микрозадач promises, а затем выполняет setTimeout или setImmediate очередь макрозадач.
Вот пример, показывающий порядок между setImmediate(), process.nextTick() и Promise.then():
const baz = () => console.log('baz');
const foo = () => console.log('foo');
const zoo = () => console.log('zoo');
const start = () => {
console.log('start');
setImmediate(baz);
new Promise((resolve, reject) => {
resolve('bar');
}).then(resolve => {
console.log(resolve);
process.nextTick(zoo);
});
process.nextTick(foo);
};
start();
// start foo bar zoo bazЭтот код сначала вызывает start(), затем вызывает foo() в очереди process.nextTick. После этого он обработает очередь микрозадач promises, которая выводит bar и добавляет zoo() в очередь process.nextTick одновременно. Затем он вызовет zoo(), который только что был добавлен. В конце вызывается baz() в очереди макрозадач.
Вышеупомянутый принцип справедлив в случаях CommonJS, но имейте в виду, что в ES Modules, например, в файлах .mjs, порядок выполнения будет другим:
// start bar foo zoo bazЭто связано с тем, что загружаемый ES Module обернут как асинхронная операция, и, таким образом, весь скрипт фактически уже находится в очереди микрозадач promises. Поэтому, когда промис немедленно разрешается, его обратный вызов добавляется в очередь микрозадач. Node.js попытается очистить очередь, прежде чем переходить к любой другой очереди, и поэтому вы увидите, что сначала выводится bar.