• Home
  • Articles
  • français
  • Mehdi Valette -

    Qu'est-ce que l'event loop

    La boucle d'événements (Event Loop)

    JavaScript s'exécute dans un processus monothread et isolé. Il envoie et reçoit constamment des requêtes de son environnement d'exécution. Le mécanisme qui détermine l'ordre d'exécution de ces tâches est appelé boucle d'événements.

    En bref

    La boucle d'événements s'exécute lorsque la pile est vide. Elle exécute d'abord toutes les microtâches en file d'attente. Une fois la file d'attente des microtâches vide, elle exécute la macrotâche suivante.

    Pile d'appels (Call Stack)

    La pile d'appels est la liste des instructions JavaScript à exécuter. Lorsque le moteur JS lit le script, il empile les instructions et les retire une fois leur exécution terminée.

    Bien que la pile d'appels soit monothread, JavaScript peut effectuer des opérations concurrentes en déléguant certaines tâches (comme la gestion des minuteurs ou les requêtes réseau) à son environnement d'exécution.

    Environnement d'exécution (Runtime)

    Un environnement d'exécution est un environnement intermédiaire entre le système d'exploitation et le code. Dans cet article, le terme « environnement d'exécution » désigne l'environnement d'exécution JavaScript. Les exemples les plus courants sont les navigateurs web et NodeJS. De nombreuses autres applications prennent en charge JavaScript pour les scripts ou les extensions, mais cet article se concentre sur les navigateurs web.

    API du navigateur (Browser API)

    Les API du navigateur constituent l'interface entre JavaScript et l'environnement d'exécution. Elles permettent d'accéder au DOM, aux minuteurs, aux entrées/sorties de fichiers et au réseau. Ces API sont appelées par le biais de fonctions JavaScript.

    Par exemple : setTimeout(func, 1000), elem.addEventListener("click", handler) et fetch(url). Toutes ces fonctions utilisent les API du navigateur. Une fois l'opération terminée, l'environnement d'exécution place le rappel ou la promesse correspondant(e) dans une file d'attente de tâches.

    Files d'attente de tâches (task queues)

    Lorsque l'environnement d'exécution termine sa tâche (par exemple, lorsqu'un minuteur expire), il ajoute une nouvelle tâche soit à la file d'attente des microtâches pour une priorité plus élevée, soit à la file d'attente des macrotâches pour une priorité plus faible.

    flowchart LR
    
    A["Pile d'appels"]
    
    B["Files d'attente de microtâches et de macrotâches"]
    
    subgraph "API du navigateur"
    
    C["Minuteurs"]
    
    D["Événements utilisateur"]
    
    E["HTTP"]
    
    F["..."]
    
    end
    
    A --> C
    
    A --> D
    
    A --> E
    
    A --> F
    
    C --> B
    
    D --> B
    
    E --> B
    
    F --> B
    
    B --> A
    

    Boucle d'événements (Event Loop)

    La boucle d'événements s'exécute lorsque la pile d'appels est vide. S'il y a des microtâches en attente, elle les exécute une par une en les ajoutant à la pile. Lorsqu'il ne reste plus de microtâches, la macrotâche suivante est exécutée.

    Si l'exécution d'une tâche planifie une nouvelle microtâche, celle-ci est traitée avant toute macrotâche ultérieure.

    Dans les navigateurs, des opérations supplémentaires peuvent avoir lieu entre les exécutions de tâches. Généralement, le navigateur exécute toutes les microtâches, puis effectue le rendu et les mises à jour de l'interface utilisateur, et n'exécute ensuite qu'une seule macrotâche.

    flowchart TB
    
    idle(["Inactif"])
    stack_empty{"Pile vide?"}
    micro_wait{"Microtâches en attente?"}
    macro_wait{"Macrotâches en attente?"}
    microtask["Pousser la microtâche suivante sur la pile"]
    macrotask["Pousser la macrotâche suivante sur la pile"]
    
    idle --> stack_empty
    
    stack_empty -- oui --> micro_wait
    
    stack_empty -- non --> idle
    
    micro_wait -- oui --> microtask
    
    micro_wait -- non --> macro_wait
    
    macro_wait -- oui --> macrotask
    
    macro_wait -- non --> idle
    
    microtask --> idle
    
    macrotask --> idle
    
    

    Remarques

    Certains environnements d'exécution contiennent plusieurs files d'attente pour les microtâches et les macrotâches. Bien que toutes les microtâches soient prioritaires sur les macrotâches, les tâches d'une même catégorie peuvent avoir des niveaux de priorité différents.

    De plus, même si les microtâches sont généralement prioritaires, les environnements d'exécution peuvent occasionnellement autoriser l'exécution de macrotâches afin d'éviter une saturation des ressources lorsque les microtâches sont constamment mises en file d'attente.