1.1 Concepts de base de l'asynchronisme
L'asynchronisme en JavaScript permet d'exécuter des tâches en arrière-plan sans bloquer le flux principal d'exécution. C'est particulièrement important pour les tâches qui peuvent prendre du temps, comme les requêtes réseau, la lecture de fichiers et les minuteries. Maintenant, on va voir les concepts de base de la programmation asynchrone en JavaScript et donner des exemples d'utilisation.
Caractère monothread de JavaScript
JavaScript est un langage monothread: ça veut dire qu'il exécute le code séquentiellement dans un seul thread. Cependant, les opérations asynchrones permettent d'effectuer des tâches en arrière-plan, libérant ainsi le flux principal pour d'autres tâches.
Event Loop (Boucle d'événements)
La boucle d'événements (Event Loop) est un mécanisme clé qui permet à JavaScript de traiter des tâches asynchrones. La boucle d'événements gère une file d'attente de messages (Message Queue) et une file d'attente de microtâches (Microtask Queue), garantissant l'exécution des opérations asynchrones.
- File d'attente de messages: contient des tâches telles que les gestionnaires d'événements, les requêtes réseau et les minuteries. Les tâches de cette file sont exécutées séquentiellement.
- File d'attente de microtâches: contient des tâches avec une priorité plus élevée par rapport aux tâches dans la file d'attente de messages. Des exemples incluent la résolution de promesses et les appels de fonctions de rappel (callbacks) dans les microtâches.
La boucle d'événements vérifie constamment les deux files et exécute les tâches lorsqu'elle trouve le flux principal libre.
Opérations asynchrones
Les opérations asynchrones permettent d'exécuter des tâches en arrière-plan. Les principaux exemples d'opérations asynchrones incluent:
- Minuteries (
setTimeout,setInterval) - Gestionnaires d'événements
- Requêtes réseau (par exemple,
XMLHttpRequest,Fetch API) - Lecture/écriture de fichiers (dans Node.js)
Voyons quelques exemples d'opérations asynchrones.
1.2 Minuteries
Les minuteries permettent d'exécuter des tâches avec un délai ou à des intervalles réguliers.
Exemple d'utilisation de setTimeout
Dans cet exemple, setTimeout exécute une fonction après 2 secondes. En conséquence, on affiche d'abord Start et End, puis après 2 secondes, Executed after 2 seconds s'affiche.
console.log('Start');
setTimeout(() => {
console.log('Executed after 2 seconds');
}, 2000);
console.log('End');
Exemple d'utilisation de setInterval
Dans cet exemple, setInterval exécute une fonction chaque seconde, incrémente un compteur et affiche sa valeur. Lorsque le compteur atteint 5, l'intervalle est arrêté avec clearInterval:
let counter = 0;
const intervalID = setInterval(() => {
counter++;
console.log(`Counter: ${counter}`);
if (counter >= 5) {
clearInterval(intervalID);
}
}, 1000);
1.3 Gestionnaires d'événements
Les gestionnaires d'événements permettent d'exécuter du code en réponse aux actions de l'utilisateur ou à d'autres événements.
Exemple d'utilisation de gestionnaires d'événements
Dans cet exemple, un gestionnaire d'événement click est ajouté à un bouton. Quand l'utilisateur clique sur le bouton, un message Button clicked! s'affiche:
<!DOCTYPE html>
<html>
<head>
<title>Exemple de gestionnaire d'événements</title>
</head>
<body>
<button id="myButton">Click me</button>
<script>
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log('Button clicked!');
});
</script>
</body>
</html>
1.4 Requêtes réseau
Les requêtes réseau permettent d'exécuter des requêtes HTTP asynchrones vers un serveur.
Exemple d'utilisation de XMLHttpRequest
Dans cet exemple, une requête GET asynchrone est effectuée vers une API, et lorsque la requête est terminée, la réponse est affichée dans la console:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
console.log(response);
}
};
xhr.send();
1.5 Event Loop en action
Pour mieux comprendre comment fonctionne l'Event Loop, examinons l'exemple suivant:
console.log('Start');
setTimeout(() => {
console.log('Timeout 1');
}, 0);
Promise.resolve().then(() => {
console.log('Promise 1');
});
setTimeout(() => {
console.log('Timeout 2');
}, 0);
Promise.resolve().then(() => {
console.log('Promise 2');
});
console.log('End');
La sortie attendue sera la suivante:
StartEndPromise 1Promise 2Timeout 1Timeout 2
Dans cet exemple, les opérations synchrones sont d'abord exécutées (console.log('Start') et console.log('End')). Ensuite les microtâches sont exécutées (gestionnaires de promesses), et seulement après les tâches de la file d'attente de messages (setTimeout).
GO TO FULL VERSION