Programmation asynchrone en TypeScript : guide complet pour débutants
Le développement web moderne est impossible sans la compréhension de la programmation asynchrone. TypeScript, en tant que surcouche de JavaScript, fournit des outils puissants pour travailler avec du code asynchrone, le rendant plus sûr et plus prévisible. Dans ce guide, nous allons décomposer les concepts clés de la programmation asynchrone en TypeScript, en commençant par les bases et en terminant par des exemples pratiques.
Qu'est-ce que la programmation asynchrone et pourquoi en a-t-on besoin ?
En programmation synchrone, le code s'exécute strictement séquentiellement : chaque opération suivante attend la fin de la précédente. Cela crée des problèmes lors du traitement de tâches longues, telles que les requêtes vers un serveur, la lecture de fichiers ou les temporisateurs. La programmation asynchrone permet d'exécuter ces tâches en arrière-plan, sans bloquer le fil d'exécution principal.
TypeScript ajoute un typage strict au JavaScript asynchrone, ce qui aide à détecter les erreurs dès la phase de compilation. Par exemple, les Promise typées permettent de savoir précisément quel type de données une fonction asynchrone va retourner.
// Code synchrone - bloque l'exécutionfunction fetchData(): string { // Opération longue return "données";}
// Code asynchrone - ne bloque pasasync function fetchDataAsync(): Promise<string> { const response = await fetch('/api/data'); return response.json();}Les bases : Callback, Promise et Async/Await
Historiquement, l'asynchronisme en JavaScript a commencé avec les fonctions callback, qui étaient passées en tant qu'arguments. Cependant, cette approche menait à "l'enfer des callbacks" — des structures profondément imbriquées, difficiles à comprendre et à déboguer.
Promises ont résolu ce problème en fournissant une syntaxe chaînée. Une Promise est un objet représentant le résultat d'une opération asynchrone, qui peut être dans l'un des trois états : pending (en attente), fulfilled (résolue) ou rejected (rejetée).
// Exemple de Promise en TypeScriptfunction loadUser(id: number): Promise<User> { return new Promise((resolve, reject) => { setTimeout(() => { if (id > 0) { resolve({ id, name: "Alice" }); } else { reject(new Error("Invalid user ID")); } }, 1000); });}
// UtilisationloadUser(1) .then(user => console.log(user)) .catch(error => console.error(error));Async/Await est un sucre syntaxique au-dessus des Promises, qui rend le code asynchrone similaire au code synchrone. Le mot-clé async avant une fonction indique qu'elle retourne une Promise, et await suspend l'exécution jusqu'à l'obtention du résultat.
// Async/Await en TypeScriptasync function getUserData(): Promise<void> { try { const user = await loadUser(1); console.log(user.name); // "Alice" } catch (error) { console.error("Erreur de chargement :", error); }}
getUserData();Typage des fonctions asynchrones en TypeScript
L'un des principaux avantages de TypeScript est le typage strict. Pour les fonctions asynchrones, il est important d'indiquer correctement le type de la Promise retournée. Si une fonction retourne une chaîne, le type sera Promise<string>. Le compilateur TypeScript vérifiera que vous n'essayez pas d'utiliser le résultat avant de l'avoir obtenu.
Examinons un exemple avec une requête API typée :
interface Todo { userId: number; id: number; title: string; completed: boolean;}
async function fetchTodo(id: number): Promise<Todo> { const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json() as Todo;}
// Utilisation avec typageasync function displayTodo(): Promise<void> { const todo = await fetchTodo