Je pense que nous ne pouvons pas discuter de la boucle d'événements en séparation de la pile, donc:
JS a trois "piles":
- pile standard pour tous les appels synchrones (une fonction en appelle une autre, etc.)
- file d'attente de microtâche (ou file d'attente de travail ou pile de microtâche) pour toutes les opérations asynchrones avec une priorité plus élevée (process.nextTick, Promises, Object.observe, MutationObserver)
- file d'attente macrotask (ou file d'attente d'événements, file d'attente de tâches, file d'attente macrotask) pour toutes les opérations asynchrones avec une priorité inférieure (setTimeout, setInterval, setImmediate, requestAnimationFrame, I / O, rendu de l'interface utilisateur)
|=======|
| macro |
| [...] |
| |
|=======|
| micro |
| [...] |
| |
|=======|
| stack |
| [...] |
| |
|=======|
Et la boucle d'événement fonctionne de cette façon:
- exécutez tout de bas en haut depuis la pile, et UNIQUEMENT lorsque la pile est vide, vérifiez ce qui se passe dans les files d'attente ci-dessus
- vérifier la micro-pile et exécuter tout ce qui s'y trouve (si nécessaire) à l'aide de la pile, une micro-tâche après l'autre jusqu'à ce que la file d'attente des microtaches soit vide ou ne nécessite aucune exécution et UNIQUEMENT puis vérifier la pile de macros
- vérifier la pile de macros et exécuter tout ce qui s'y trouve (si nécessaire) à l'aide de la pile
La pile de Mico ne sera pas touchée si la pile n'est pas vide. La pile de macros ne sera pas touchée si la micro-pile n'est pas vide OU ne nécessite aucune exécution.
Pour résumer: la file d'attente de microtask est presque la même que la file d'attente de macrotask, mais ces tâches (process.nextTick, Promises, Object.observe, MutationObserver) ont une priorité plus élevée que les macrotasks.
Le micro est comme la macro mais avec une priorité plus élevée.
Ici vous avez le code "ultime" pour tout comprendre.
console.log('stack [1]');
setTimeout(() => console.log("macro [2]"), 0);
setTimeout(() => console.log("macro [3]"), 1);
const p = Promise.resolve();
for(let i = 0; i < 3; i++) p.then(() => {
setTimeout(() => {
console.log('stack [4]')
setTimeout(() => console.log("macro [5]"), 0);
p.then(() => console.log('micro [6]'));
}, 0);
console.log("stack [7]");
});
console.log("macro [8]");
/* Result:
stack [1]
macro [8]
stack [7], stack [7], stack [7]
macro [2]
macro [3]
stack [4]
micro [6]
stack [4]
micro [6]
stack [4]
micro [6]
macro [5], macro [5], macro [5]
--------------------
but in node in versions < 11 (older versions) you will get something different
stack [1]
macro [8]
stack [7], stack [7], stack [7]
macro [2]
macro [3]
stack [4], stack [4], stack [4]
micro [6], micro [6], micro [6]
macro [5], macro [5], macro [5]
more info: https://blog.insiderattack.net/new-changes-to-timers-and-microtasks-from-node-v11-0-0-and-above-68d112743eb3
*/
while (task = todo.shift()) task();