Async JavaScript - 00 - Introduction

Pourquoi JavaScript est single-threaded, le modèle event-driven, et ce que cette serie va couvrir en profondeur.

Async JavaScript - Introduction

Ce que tu vas apprendre

  • Pourquoi JavaScript est mono-thread (et pourquoi c'est un choix delibere)
  • Le modèle event-driven en quelques mots
  • L'histoire du "callback hell" et comment on s'en est sorti
  • Le plan complet de cette serie de 18 articles

Prerequisites

  • Savoir écrire du JavaScript basique (variables, fonctions, objets)
  • Avoir deja utilise setTimeout ou fetch au moins une fois
  • Une curiosite sincere pour comprendre ce qui se passe "sous le capot"

Il y a quelques annees, j'ai déployé une page qui faisait un appel API synchrone avec XMLHttpRequest en mode bloquant. Le bouton "Valider" gelait le navigateur pendant 3 secondes. Un collegue m'a regarde et m'a dit : "Tu sais que le navigateur a un seul thread pour le rendu ET ton JS, hein ?" Je ne savais pas. Pas vraiment. Et je parie que toi aussi, tu as deja eu ce moment ou ton UI se fige et tu ne comprends pas pourquoi.

Ce jour-la, j'ai compris qu'on ne peut pas écrire du JavaScript correct sans comprendre son modèle d'exécution asynchrone. Pas juste "utiliser async/await" -- vraiment comprendre ce qui se passe en dessous.

Pourquoi un seul thread ?

JavaScript a ete créé en 1995 par Brendan Eich en 10 jours. Le but : rendre les pages web interactives. Pas faire du calcul scientifique, pas gerer des serveurs. Manipuler le DOM.

Et le DOM, c'est un arbre partage. Si deux threads modifient le meme noeud en meme temps, c'est la catastrophe. Plutot que d'ajouter des mutex et des locks (comme Java), Brendan a fait le choix radical : un seul thread d'exécution.

Thread principal JS
|
|-- Executer le code
|-- Mettre a jour le DOM
|-- Gerer les evenements utilisateur
|-- Tout ca, un truc a la fois

C'est simple. C'est previsible. Et ca marche -- tant que tu ne bloques pas ce thread.

Le modèle event-driven

Si JS est mono-thread, comment fait-il pour gerer des requêtes réseau, des timers, des clics utilisateur en "parallèle" ? La réponse : il ne le fait pas lui-meme. Il délégué.

+-----------------+     +------------------+
|   Ton code JS   |---->|  APIs du browser |
|  (single thread)|     |  (multi-thread)  |
+-----------------+     +------------------+
        ^                       |
        |                       v
        +------< Event Loop <---+

Ton code enregistre un callback. Le navigateur (ou Node.js) fait le travail en arriere-plan. Quand c'est fini, le callback est place dans une file d'attente. L'event loop le récupéré et l'exécuté quand le thread principal est libre.

C'est elegant. C'est aussi la source de 90% des bugs asynchrones que tu rencontreras dans ta carriere.

L'ere du callback hell

Avant les Promises (ES2015), tout passait par des callbacks. Et ca donnait ca :

javascriptgetUser(userId, function(user) {
  getOrders(user.id, function(orders) {
    getOrderDetails(orders[0].id, function(details) {
      getShippingInfo(details.shippingId, function(shipping) {
        updateUI(user, orders, details, shipping);
      });
    });
  });
});

On appelle ca la "pyramide de la mort". Pas juste parce que c'est moche -- c'est aussi un cauchemar pour la gestion d'erreurs. Chaque niveau de callback doit gerer ses propres erreurs. Oublie un if (err) et ton application plante silencieusement.

La communauté a reagi : d'abord avec des librairies comme async.js, puis avec les Promises, et enfin avec async/await. Mais tout ca repose sur le meme mecanisme fondamental : l'event loop.

Ce que cette serie couvre

Voici le plan complet des 18 articles :

# Sujet
00 Introduction (tu es ici)
01 La Call Stack
02 L'Event Loop
03 Les Macrotasks
04 Les Microtasks
05 Ordre d'exécution
06 Les Promises en profondeur
07 Async/Await
08 Gestion d'erreurs async
09 Promise.all, race, allSettled, any
10 Generators et itérateurs async
11 Streams et backpressure
12 Web Workers
13 SharedArrayBuffer et Atomics
14 AbortController et annulation
15 Patterns avances (retry, debounce, throttle)
16 Async dans les frameworks (React, Vue)
17 Debugging et profiling async

Chaque article contient du code executable, des diagrammes ASCII, et des exercices. Je ne vais pas juste te dire "voici comment ca marche" -- je vais te montrer pourquoi ca marche comme ca, et ce qui se passe quand ca ne marche pas.

Mon approche

Je deteste les tutoriels qui survolent les sujets. "Utilise async/await, c'est magique !" Non. Ce n'est pas magique. C'est du sucre syntaxique au-dessus de Promises, qui sont elles-memes au-dessus de callbacks, qui dependent de l'event loop, qui interagit avec les APIs du navigateur ou de Node.js.

Si tu veux juste copier-coller du code, cette serie n'est pas pour toi. Si tu veux comprendre ce qui se passe vraiment quand tu ecris await fetch(url), alors on va bien s'entendre.

Résumé

  • JavaScript est mono-thread par design : un thread pour le code, le DOM, et les événements
  • Le modèle event-driven permet de simuler le parallélisme en deleguant aux APIs externes
  • Le callback hell etait le prix a payer avant Promises et async/await
  • Cette serie de 18 articles couvre tout, de la call stack aux patterns avances

Suivant : La Call Stack

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.