La nature asynchrone de JavaScript peut sembler magique jusqu'à ce que vous plongez dans la mécanique. La sauce secrète réside dans sa boucle d'événements, qui orchestre deux acteurs clés : les microtâches et les macrotâches. Mais que sont-ils, comment fonctionnent-ils et pourquoi sont-ils importants ? Perçons le mystère avec une analyse approfondie, des exemples et des conseils pour maîtriser ce concept.
Le moteur JavaScript exécute le code dans un seul thread. Pour gérer les opérations asynchrones, il s'appuie sur la boucle d'événements, qui assure la coordination entre la pile d'appels et les files d'attente de tâches. Ces files d'attente de tâches sont divisées en deux catégories : les microtâches et les macrotâches.
Les microtâches sont des tâches hautement prioritaires qui doivent être exécutées dès que le code JavaScript en cours d'exécution est terminé et que la pile d'appels est vide. Ils garantissent des actions de suivi rapides et des états cohérents. Les exemples courants incluent :
Les macrotâches sont des tâches de moindre priorité que la boucle d'événements ne gère qu'une fois que toutes les microtâches ont été exécutées. Ils gèrent des opérations différées plus importantes et des événements externes. Les exemples courants incluent :
Il existe également requestAnimationFrame, qui ne fait partie d'aucune des deux files d'attente. Il se synchronise avec le cycle de rendu du navigateur, ce qui le rend idéal pour des animations fluides.
Voici comment la boucle d'événements traite les tâches :
Cette hiérarchisation garantit que les tâches hautement prioritaires telles que les promesses sont résolues avant les opérations moins urgentes comme les minuteries.
Vous trouverez ci-dessous un extrait de code pratique pour illustrer l'interaction entre le code synchrone, les microtâches, les macrotâches et requestAnimationFrame :
console.log('Synchronous code starts'); // Macrotask: setTimeout setTimeout(() => { console.log('Macrotask: setTimeout'); }, 0); // Macrotask: setInterval const intervalId = setInterval(() => { console.log('Macrotask: setInterval'); clearInterval(intervalId); }, 100); // Microtask: Promise Promise.resolve().then(() => { console.log('Microtask: Promise then 1'); Promise.resolve().then(() => { console.log('Microtask: Promise then 2'); }); }); // Microtask: MutationObserver const observer = new MutationObserver(() => { console.log('Microtask: MutationObserver'); }); const targetNode = document.createElement('div'); observer.observe(targetNode, { attributes: true }); targetNode.setAttribute('data-test', 'true'); // Macrotask: MessageChannel const channel = new MessageChannel(); channel.port1.onmessage = () => { console.log('Macrotask: MessageChannel'); }; channel.port2.postMessage('Test'); // requestAnimationFrame requestAnimationFrame(() => { console.log('Outside task queues: requestAnimationFrame'); }); console.log('Synchronous code ends');
La séquence de sortie permet de clarifier la priorisation :
Bien qu'il ne fasse pas partie des files d'attente de tâches, requestAnimationFrame joue un rôle unique dans l'asynchronie. Il planifie l'exécution du code avant la prochaine repeinture du navigateur, garantissant ainsi un minimum de pertes d'images et des animations plus fluides.
L'interaction entre les microtâches, les macrotâches et la boucle d'événements est au cœur de l'asynchronie de JavaScript. En comprenant et en exploitant ces concepts, vous pouvez écrire un code plus efficace, plus maintenable et plus performant. N'oubliez pas : les microtâches en premier, les macrotâches en second et requestAnimationFrame pour le peaufinage visuel. Bon codage !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!