setImmediate()
verstehen
Wenn du ein Codefragment asynchron, aber so schnell wie möglich ausführen möchtest, ist eine Möglichkeit die setImmediate()
-Funktion, die von Node.js bereitgestellt wird:
setImmediate(() => {
// tue etwas
})
Jede als Argument an setImmediate()
übergebene Funktion ist ein Callback, der in der nächsten Iteration der Event-Loop ausgeführt wird.
Wie unterscheidet sich setImmediate()
von setTimeout(() => {}, 0)
(Übergabe eines 0ms-Timeouts) und von process.nextTick()
und Promise.then()
?
Eine Funktion, die an process.nextTick()
übergeben wird, wird in der aktuellen Iteration der Event-Loop ausgeführt, nachdem die aktuelle Operation beendet ist. Das bedeutet, dass sie immer vor setTimeout
und setImmediate
ausgeführt wird.
Ein setTimeout()
-Callback mit einer Verzögerung von 0 ms ist sehr ähnlich wie setImmediate()
. Die Ausführungsreihenfolge hängt von verschiedenen Faktoren ab, aber beide werden in der nächsten Iteration der Event-Loop ausgeführt.
Ein process.nextTick
-Callback wird zur process.nextTick-Warteschlange hinzugefügt. Ein Promise.then()
-Callback wird zur Microtask-Warteschlange der Promises hinzugefügt. Ein setTimeout
- oder setImmediate
-Callback wird zur Macrotask-Warteschlange hinzugefügt.
Die Event-Loop führt zuerst Aufgaben in der process.nextTick-Warteschlange aus, dann die Microtask-Warteschlange der Promises und dann die setTimeout
- oder setImmediate
-Macrotask-Warteschlange.
Hier ist ein Beispiel, um die Reihenfolge zwischen setImmediate()
, process.nextTick()
und Promise.then()
zu zeigen:
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
Dieser Code ruft zuerst start()
auf, dann foo()
in der process.nextTick-Warteschlange. Danach wird die Microtask-Warteschlange der Promises verarbeitet, die "bar" ausgibt und gleichzeitig zoo()
in der process.nextTick-Warteschlange hinzufügt. Dann wird zoo()
aufgerufen, das gerade hinzugefügt wurde. Am Ende wird baz()
in der Macrotask-Warteschlange aufgerufen.
Das oben genannte Prinzip gilt in CommonJS-Fällen, aber beachte, dass in ES-Modulen, z. B. mjs
-Dateien, die Ausführungsreihenfolge anders ist:
// start bar foo zoo baz
Dies liegt daran, dass das geladene ES-Modul als asynchrone Operation verpackt wird und das gesamte Skript daher bereits in der Microtask-Warteschlange der Promises enthalten ist. Wenn also das Promise sofort aufgelöst wird, wird sein Callback an die Microtask-Warteschlange
angehängt. Node.js wird versuchen, die Warteschlange zu leeren, bevor es zu einer anderen Warteschlange übergeht, und daher wird zuerst "bar" ausgegeben.