Concurrence et multithreading en JavaScript : de A à Z

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Concurrence et multithreading en JavaScript : de A à Z



JavaScript est historiquement un langage monothread fonctionnant dans le paradigme de la programmation événementielle. Cependant, le JavaScript moderne (notamment dans l'environnement Node.js) offre des outils puissants pour travailler avec la concurrence et le multithreading. Dans cet article, nous allons voir comment fonctionnent l'Event Loop, les Promises, async/await, les Worker Threads et le clustering, et comment utiliser ces mécanismes pour améliorer les performances de vos applications.



1. Event Loop : le fondement de la concurrence en JavaScript



L'Event Loop est le cœur du modèle asynchrone de JavaScript. Il permet de traiter de nombreuses opérations sans bloquer le thread d'exécution principal. Dans Node.js, l'Event Loop gère les files d'attente de tâches (macrotasks et microtasks), assurant des entrées-sorties non bloquantes.



Exemple de fonctionnement de l'Event Loop :



console.log('Début');

setTimeout(() => { console.log('Timer 1');}, 0);

process.nextTick(() => { console.log('nextTick');});

Promise.resolve().then(() => { console.log('Promise');});

console.log('Fin');

// Sortie :// Début// Fin// nextTick// Promise// Timer 1


Il est important de comprendre l'ordre d'exécution : code synchrone → microtasks (process.nextTick, Promise.then) → macrotasks (setTimeout, setInterval).



2. Promises et async/await : gestion de l'asynchrone



Les Promises sont des objets représentant le résultat d'une opération asynchrone. Elles permettent d'éviter le « callback hell » et de construire des chaînes d'appels. async/await est un sucre syntaxique sur les Promises, rendant le code asynchrone similaire au code synchrone.



Exemple avec async/await :



const fetchData = async (url) => {  const response = await fetch(url);  if (!response.ok) {    throw new Error(`Erreur HTTP : ${response.status}`);  }  return await response.json();};

const main = async () => { try { const data = await fetchData('https://api.example.com/data'); console.log('Données reçues :', data); } catch (error) { console.error('Erreur :', error.message); }};

main();


Cette approche permet d'exécuter plusieurs opérations asynchrones en parallèle avec Promise.all() :



const [user, posts] = await Promise.all([  fetchUser(userId),  fetchPosts(userId)]);console.log(user, posts);


3. Worker Threads : véritable multithreading dans Node.js



Depuis Node.js 10.5.0, le module worker_threads permet de créer de véritables threads pour exécuter des tâches intensives en CPU. Chaque Worker fonctionne dans un thread séparé avec sa propre instance V8.



Exemple de création d'un Worker :



// main.jsconst { Worker } = require('worker_threads');

const runWorker = (workerData) => { return new Promise((resolve, reject) => { const worker = new Worker('./worker.js', { workerData });

worker.on('message', resolve); worker.on('error', reject); worker.on('exit', (code) => { if (code !== 0) { reject(new Error(`Worker arrêté avec le code ${code}`)); } }); });};

const main = async () => { const result = await runWorker({ iterations: 1000000 }); console.log('Résultat :', result);};

main();


// worker.jsconst { parentPort, workerData } = require('worker_threads');

const heavyComputation = (iterations) => { let result = 0; for (let i = 0; i < iterations; i++) { result += Math.sqrt(i); } return result;};

const result = heavyComputation(workerData.iterations);parentPort.postMessage(result);


Les Worker Threads sont idéaux pour les tâches qui bloquent l'Event Loop : traitement d'images, calculs mathématiques, analyse de gros fichiers.



4. Clustering : mise à l'échelle sur plusieurs processus

\

Blogs

Book Recommendations