Fonctionnement de Javascript : boucle d'événement

Réimpression : lien d'origine

Qu'est-ce qu'une boucle événementielle ?

Nous commençons par une affirmation étrange - alors que le code JavaScript asynchrone (comme setTimeout me) est autorisé, JavaScript lui-même n'a jamais eu de concept direct d'asynchronisme intégré jusqu'à ES6. Le moteur JavaScript ne fait jamais rien d'autre que d'exécuter un seul bloc du programme à un moment donné.

Alors, qui dit au moteur JS d'exécuter votre bloc ? En fait, le moteur JS ne s'exécute pas de manière isolée, mais dans un environnement hébergé, qui pour la plupart des développeurs est un navigateur Web typique ou Node.js. En fait, aujourd'hui, JavaScript est intégré à tout, des robots aux ampoules électriques. Chaque appareil individuel représente un type différent d'environnement d'hébergement pour JS Engine.

Tous les environnements ont en commun un mécanisme intégré appelé boucle d'événements qui gère l'exécution de plusieurs blocs dans un programme chaque fois que JS Engine est appelé.

Cela signifie qu'un moteur JS n'est qu'un environnement d'exécution à la demande pour tout code JS arbitraire. Le moment de planifier l'événement (exécution du code JS) est l'environnement environnant.

Ainsi, par exemple, lorsque votre programme JavaScript fait une requête Ajax pour obtenir des données du serveur, vous définissez le code "réponse" ("callback") dans la fonction, et le moteur JS indique à l'environnement d'hébergement : "Hé, je Je suis pour l'instant en pause d'exécution, mais dès que vous avez terminé cette requête réseau et que vous avez des données, rappelez cette fonction."

Le navigateur est ensuite configuré pour écouter les réponses du réseau et planifiera l'exécution d'une fonction de rappel en l'insérant dans la boucle d'événements lorsque quelque chose doit vous être renvoyé. Regardons l'image ci-dessous :

1_FA9NGxNB6-v1oI2qGEtlRQ.png

Quelles sont ces API Web ? Essentiellement, ce sont des fils auxquels vous n'avez pas accès et vous pouvez les appeler. Ils font partie du navigateur qui initie la concurrence. Si vous êtes un développeur Node.js, ce sont des API C++.

Alors, qu'est-ce qu'une boucle d'événements exactement ?

1_KGBiAxjeD9JT2j6KDo0zUg.png

La boucle d'événements a un travail simple - écouter la pile d'appels et la file d'attente de rappel. Si la pile d'appels est vide, la boucle d'événements saisira le premier événement de la file d'attente et le poussera dans la pile d'appels, exécutant efficacement l'événement. Ces itérations sont appelées ticks dans la boucle d'événements et chaque événement n'est qu'un rappel de fonction.

console.log('Hi');
setTimeout(function cb1() { 
    console.log('cb1');
}, 5000);
console.log('Bye');
复制代码

"Exécutons" ce code et voyons ce qui se passe :

  1. Le statut est clair. La console du navigateur est effacée et la pile des appels est vide.

1.png

  1. console.log('Hi') est ajouté à la pile des appels

2.png

  1. console.log('Hi') est exécuté.

3.png

  1. console.log('Hi') est supprimé de la pile d'appels.

4.png

  1. setTimeout(function cb1() { ... }) est ajouté à la pile d'appels.

5.png

  1. setTimeout(fonction cb1() { ... }) s'exécute. Le navigateur créera le minuteur dans le cadre de l'API Web. Il gère le compte à rebours pour vous.

6.png

  1. setTimeout(function cb1() { ... }) lui-même s'est terminé et a été supprimé de la pile d'appels.

7.png

  1. console.log('Bye') est ajouté à la pile d'appels.

8.png

  1. console.log('Bye') s'exécute.

9.png

  1. console.log('Bye') est supprimé de la pile d'appels.

10.png

  1. Après au moins 5000ms, le temporisateur se termine et pousse le rappel cb1 vers la "Callback Queue".

11.png

  1. La boucle d'événement cb1 obtient de la file d'attente de rappel et la pousse vers la pile d'appels.

12.png

  1. cb1 exécute et ajoute console.log('cb1') à la pile d'appels.

13.png

  1. console.log('cb1') s'exécute.

14.png

  1. console.log('cb1') est supprimé de la pile d'appels.

15.png

  1. cb1 est supprimé de la pile d'appels.

16.png

Récapitulatif rapide :

1_TozSrkk92l8ho6d8JxqF_w.gif

Fait intéressant, ES6 spécifie le fonctionnement de la boucle d'événements, ce qui signifie qu'elle relève techniquement du moteur JS, qui n'agit plus uniquement comme un environnement d'hébergement. L'une des principales raisons de ce changement était l'introduction de Promises dans ES6, car ce dernier nécessitait un accès à un contrôle direct et précis des opérations de planification sur la file d'attente de la boucle d'événements (dont nous parlerons en détail plus tard).

Fonctionnement de setTimeout(...)

Il est important de noter que setTimeout(...) ne place pas automatiquement le rappel dans la file d'attente de la boucle d'événements. Il définit une minuterie. Lorsque le minuteur expire, l'environnement placera votre rappel dans la boucle d'événements afin qu'un tick futur le récupère et l'exécute. Jetez un oeil à ce code:

setTimeout(myCallback, 1000);

Cela ne signifie pas que myCallback s'exécutera en 1 000 ms, mais myCallback l'ajoutera à la file d'attente de la boucle d'événements en 1 000 ms. Cependant, il peut y avoir d'autres événements ajoutés plus tôt dans la file d'attente - vos rappels devront attendre.

Voir le code ci-dessous :

setTimeout(function() {
    console.log('callback');
}, 0);
console.log('Bye');
复制代码

Bien que le temps d'attente soit défini sur 0 ms, le résultat dans la console du navigateur sera le suivant :

Hi
Bye
callback
复制代码

Je suppose que tu aimes

Origine juejin.im/post/6950488674488287246
conseillé
Classement