J'ai travaillé en tant que développeur Java et je me souviens pour la première fois du jour où j'ai été en contact avec des promesses en JavaScript. Même si le concept semblait simple, je n’arrivais toujours pas à comprendre pleinement comment fonctionnait Promises. Cela a changé lorsque j'ai commencé à les utiliser dans des projets et que j'ai compris les cas qu'ils résolvaient. Puis vint le moment AHA et tout devint plus clair. Au fil du temps, les promesses sont devenues une arme précieuse sur ma ceinture à outils. C'est étrangement satisfaisant de pouvoir les utiliser au travail et résoudre la gestion asynchrone entre les fonctions.
Vous rencontrez probablement des promesses pour la première fois lors de la récupération de données à partir d'une API, ce qui est également l'exemple le plus courant. Récemment, j'ai été interviewé et devinez quelle était la première question « Pouvez-vous me dire la différence entre Promise et Async Await ? Je m’en réjouis car je considère que c’est un bon point de départ pour mieux savoir comment le demandeur comprend le fonctionnement des mécanismes. Cependant, il utilise principalement d’autres bibliothèques et frameworks. Cela m'a permis d'écrire les différences et de décrire les bonnes pratiques pour gérer les erreurs de fonction asynchrone.
Commençons par la question initiale : « Quelle est la promesse ? » Promise est un espace réservé pour la valeur que nous ne connaissons pas encore mais nous l'obtiendrons grâce à un calcul/une fonction asynchrone. Si la promesse se déroule bien, nous obtiendrons le résultat. Si la promesse ne se passe pas bien, elle renverra une erreur.
Vous définissez Promise en appelant son constructeur et en lui transmettant deux fonctions de rappel : resolve et reject.
const newPromise = new Promise((resolve, reject) => { resolve('Hello'); // reject('Error'); });
Nous appelons la fonction de résolution lorsque nous voulons résoudre avec succès la promesse. rejeter sert à rejeter la promesse dans le cas où une erreur se produit lors de l'évaluation de notre logique.
Nous utilisons ensuite la fonction intégrée pour obtenir le résultat de la promesse. Il a deux rappels passés, un résultat et une erreur. Le résultat est appelé lorsque la promesse est résolue avec succès par la fonction solve. Si la promesse n'est pas résolue, la deuxième erreur de fonction est appelée. Cette fonction est déclenchée soit par un rejet, soit par une autre erreur générée.
newPromise.then(result => { console.log(result); // Hello }, error => { console.log("There shouldn't be an error"); });
Dans notre exemple, nous obtiendrons le résultat Bonjour car nous avons réussi à résoudre la promesse.
Lorsque la promesse est rejetée, son deuxième rappel d'erreur est toujours invoqué.
const newPromise1 = new Promise((resolve, reject) => { reject('An error occurred in Promise1'); }); newPromise1.then( (result) => { console.log(result); // It is not invoked }, (error) => { console.log(error); // 'An error occurred in Promise1' } );
Une approche plus recommandée pour sa clarté consiste à utiliser la méthode catch intégrée.
const newPromise2 = new Promise((resolve, reject) => { reject('An error occurred in Promise2'); }); newPromise2 .then((result) => { console.log(result); // It is not invoked }) .catch((error) => { console.log(error); // 'An error occurred in Promise2' });La méthode
catch est chaînée et a fourni son propre rappel d'erreur. Il est invoqué lorsque la promesse est rejetée.
Les deux versions fonctionnent bien mais le chaînage est IMO plus lisible et il est pratique lors de l'utilisation d'autres méthodes intégrées que nous aborderons plus en détail.
Le résultat d'une promesse pourrait probablement être une autre promesse. Dans ce cas, nous pouvons enchaîner un nombre arbitraire de fonctions then.
getJSON('categories.json') .then(categories => { console.log('Fetched categories:', categories); return getJSON(categories[0].itemsUrl); }) .then(items => { console.log('Fetched items:', items); return getJSON(items[0].detailsUrl); }) .then(details => { console.log('Fetched details:', details); }) .catch(error => { console.error('An error has occurred:', error.message); });
Dans notre exemple, il sert à affiner les résultats de recherche pour obtenir des données détaillées. Chaque fonction then peut également avoir son rappel d'erreur. Si nous nous soucions uniquement de détecter toute erreur dans la chaîne d’appels, nous pouvons alors exploiter la fonction catch. Il sera évalué si l'une des promesses renvoie une erreur.
Parfois, nous voulons attendre les résultats de promesses plus indépendantes, puis agir en fonction des résultats. Nous pouvons utiliser la fonction intégrée Promise.all si nous ne nous soucions pas de l'ordre dans lequel les promesses ont été résolues.
Promise.all([ getJSON('categories.json'), getJSON('technology_items.json'), getJSON('science_items.json') ]) .then(results => { const categories = results[0]; const techItems = results[1]; const scienceItems = results[2]; console.log('Fetched categories:', categories); console.log('Fetched technology items:', techItems); console.log('Fetched science items:', scienceItems); // Fetch details of the first item in each category return Promise.all([ getJSON(techItems[0].detailsUrl), getJSON(scienceItems[0].detailsUrl) ]); }) .then(detailsResults => { const laptopDetails = detailsResults[0]; const physicsDetails = detailsResults[1]; console.log('Fetched laptop details:', laptopDetails); console.log('Fetched physics details:', physicsDetails); }) .catch(error => { console.error('An error has occurred:', error.message); });
Promise.all prend un tableau de promesses et renvoie un tableau de résultats. Si l'une des promesses est rejetée, alors Promise.all est également rejetée.
Une autre fonctionnalité intégrée est Promise.race. Il est utilisé lorsque vous disposez de plusieurs fonctions asynchrones - Promesses - et que vous souhaitez les exécuter.
Promise.race([ getJSON('technology_items.json'), getJSON('science_items.json') ]) .then(result => { console.log('First resolved data:', result); }) .catch(error => { console.error('An error has occurred:', error.message); });
L'exécution des promesses peut prendre des temps différents et Promise.race évalue la première promesse résolue ou rejetée du tableau. Il est utilisé lorsque nous ne nous soucions pas de la commande mais que nous voulons le résultat de l'appel asynchrone le plus rapide.
Comme vous pouvez le constater, l'écriture de promesses nécessite beaucoup de code passe-partout. Heureusement, nous disposons de la fonctionnalité native Async Await, qui rend l'utilisation des promesses encore plus facile. Nous marquons une fonction par le mot async et par là, nous disons que quelque part dans le code nous appellerons la fonction asynchrone et que nous ne devrions pas l'attendre. Ensuite, la fonction asynchrone est appelée avec le mot wait.
const fetchData = async () => { try { // Fetch the categories const categories = await getJSON('categories.json'); console.log('Fetched categories:', categories); // Fetch items from the first category (Technology) const techItems = await getJSON(categories[0].itemsUrl); console.log('Fetched technology items:', techItems); // Fetch details of the first item in Technology (Laptops) const laptopDetails = await getJSON(techItems[0].detailsUrl); console.log('Fetched laptop details:', laptopDetails); } catch (error) { console.error('An error has occurred:', error.message); } }; fetchData();
Notre fetchData est marqué comme asynchrone et il nous permet d'utiliser wait pour gérer les appels asynchrones à l'intérieur de la fonction. Nous appelons d'autres promesses et elles seront évaluées les unes après les autres.
Nous utilisons le bloc try...catch si nous voulons gérer les erreurs. L'erreur rejetée est ensuite détectée dans le bloc catch et nous pouvons agir dessus comme si nous enregistrions l'erreur.
Ce sont deux fonctionnalités de la gestion JavaScript avec du code asynchrone. La principale différence réside dans la syntaxe lorsque les promesses utilisent le chaînage avec then et catch, mais la syntaxe d'attente asynchrone est plus synchrone. Cela facilite la lecture. La gestion des erreurs pour l'attente asynchrone est plus simple lorsqu'elle exploite le bloc try...catch. C’est une question que vous pouvez facilement poser lors de l’entretien. Au cours de la réponse, vous pouvez approfondir la description des deux et mettre en évidence ces différences.
Fonctionnalités promises
Bien sûr, vous pouvez utiliser toutes les fonctionnalités avec l'attente asynchrone. Par exemple Promise.all.
const fetchAllData = async () => { try { // Use await with Promise.all to fetch multiple JSON files in parallel const [techItems, scienceItems, laptopDetails] = await Promise.all([ getJSON('technology_items.json'), getJSON('science_items.json'), getJSON('laptops_details.json') ]); console.log('Fetched technology items:', techItems); console.log('Fetched science items:', scienceItems); console.log('Fetched laptop details:', laptopDetails); } catch (error) { console.error('An error occurred:', error.message); } };
Les promesses sont une fonctionnalité fondamentale de JavaScript pour gérer le code asynchrone. Voici les principales façons dont il est utilisé :
Comme déjà montré dans les exemples ci-dessus, il s'agit de l'un des cas d'utilisation les plus utilisés pour les promesses et vous travaillez avec lui quotidiennement.
La lecture et l'écriture de fichiers de manière asynchrone peuvent être effectuées à l'aide de promesses, notamment via le module Node.js fs.promises
import * as fs from 'fs/promises'; const writeFileAsync = async (filePath, content, options = {}) => { try { await fs.writeFile(filePath, content, options); console.log(`File successfully written to ${filePath}`); } catch (error) { console.error(`Error writing file to ${filePath}:`, error.message); } }; const filePath = 'output.txt'; const fileContent = 'Hello, this is some content to write to the file!'; const fileOptions = { encoding: 'utf8', flag: 'w' }; // Optional file write options writeFileAsync(filePath, fileContent, fileOptions);
Axios est une bibliothèque que vous devriez connaître. Axios gère les requêtes HTTP dans le client et est largement utilisé.
Express est un framework Web pour Node.js. Il facilite la création d'applications Web et d'API, et lorsque vous utilisez des promesses avec Express, votre code reste propre et facile à gérer.
Tous les exemples peuvent être trouvés sur : https://github.com/PrincAm/promise-example
Les promesses sont un élément fondamental de JavaScript, essentiel pour gérer les tâches asynchrones dans le développement Web. Qu'il s'agisse de récupérer des données, de travailler avec des fichiers ou d'utiliser des bibliothèques populaires comme Axios et Express, vous utiliserez fréquemment des promesses dans votre code.
Dans cet article, nous avons exploré ce que sont les promesses, comment définir et récupérer leurs résultats et comment gérer efficacement les erreurs. Nous avons également couvert des fonctionnalités clés telles que le chaînage, Promise.all et Promise.race. Enfin, nous avons introduit la syntaxe d'attente asynchrone, qui offre un moyen plus simple de travailler avec les promesses.
Comprendre ces concepts est crucial pour tout développeur JavaScript, car ce sont des outils sur lesquels vous compterez quotidiennement.
Si vous ne l'avez pas encore essayé, je vous recommande d'écrire un simple extrait de code pour récupérer les données d'une API. Vous pouvez commencer avec une API amusante avec laquelle expérimenter. De plus, tous les exemples et extraits de code sont disponibles dans ce référentiel pour que vous puissiez les explorer.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3