Tenir ses promesses avec JavaScript

JavaScript, de par sa popularité et ses améliorations récentes, devient de plus en plus le meilleur ami du programmeur Web. Et comme tous les meilleurs amis, JavaScript tient ses promesses. 

Cela peut sembler un peu étrange, mais c’est vrai. La plupart des navigateurs actuels prennent en charge ce que l’on appelle l’objet Promise. Une promesse est tout à fait comme une fonction dans la mesure où elle représente un morceau de code ou une tâche que vous aimeriez exécuter à un moment donné..

Voici à quoi ressemble une promesse.

var myPromise = new Promise (function (résoudre, rejeter) // La tâche à exécuter va ici.);

Vous pouvez voir ici que lorsque nous créons une promesse, nous lui donnons un seul argument, qui est une fonction contenant du code que nous aimerions exécuter ultérieurement. Vous avez peut-être aussi remarqué les deux arguments de la fonction transmis à la promesse, résoudre et rejeter. Ce sont aussi des fonctions et sont notre façon de dire à la promesse si elle a fait ce qu’elle avait promis de faire. Voici comment vous les utiliseriez:

var myPromise = new Promise (function (résoudre, rejeter) if (true) résoudre ('Hello Tuts + fans!'); else rejeter ('Aww, n'a pas fonctionné.'););

Cette promesse va évidemment toujours se résoudre car le si déclaration sera toujours vrai. C’est juste à des fins d’apprentissage - nous ferons quelque chose de plus réaliste plus tard - mais imaginons de remplacer vrai avec un extrait de code que vous n'étiez pas sûr à 100% allait travailler.

Maintenant que nous avons créé une promesse, comment l'utilisons-nous? Eh bien, nous devons dire ce que ces résoudre et rejeter les fonctions sont. Nous faisons cela en utilisant la promesse puis méthode.

myPromise.then (function (result) // Résoudre le rappel. console.log (result);, function (result) // Refuser le rappel. console.error (result););

Parce que notre déclaration si passe toujours son vrai Si vous cochez cette case, le code ci-dessus indiquera toujours "Bonjour les fans!" à la console. Il le fera aussi immédiatement. En effet, le code contenu dans le constructeur de notre promesse est synchrone, ce qui signifie qu'il n'attend aucune opération à exécuter. Il dispose de toutes les informations nécessaires pour continuer et le fait dans les meilleurs délais.. 

Les promesses brillent cependant lorsqu'il s'agit de tâches asynchrones, tâches où vous ne savez pas exactement quand la promesse sera remplie. Un exemple concret de tâche asynchrone consiste à récupérer une ressource, par exemple un fichier JSON, via AJAX. Nous ne savons pas combien de temps le serveur va prendre pour répondre, et cela peut même échouer. Ajoutons quelques AJAX à notre code de promesse.

var myPromise = new Promise (function (résoudre, rejeter) // Configuration et chargement standard des demandes AJAX. var request = new XMLHttpRequest (); // Demander un commentaire d'utilisateur à partir de notre faux blog. request.open ('GET', ' http://jsonplaceholder.typicode.com/posts/1 '); // Définition de la fonction à appeler lorsque la ressource est chargée request.onload = function () if (request.status === 200) resolution (request request); else rejette ('Page chargée, mais l'état n'est pas correct.');; // Définit la fonction à appeler lorsque le chargement échoue. request.onerror = function () rejette ('Aww, n'a pas fait \' t travailler du tout. '); request.send (););

Le code ici est juste du code JavaScript standard pour exécuter une requête AJAX. Nous demandons une ressource, dans ce cas un fichier JSON à une URL spécifiée, et attendons qu'il réponde. Nous ne saurons jamais exactement quand. Et nous ne souhaitons évidemment pas arrêter l'exécution du script pour l'attendre, alors que faisons-nous? 

Heureusement, nous avons mis ce code dans une promesse. En le mettant ici, nous disons en gros: "Hey morceau de code, je dois y aller tout de suite mais je t'appellerai plus tard pour te dire quand exécuter. Promets-moi de le faire et de me dire quand tu as fini? " Et le code dira: "Oui, bien sûr. Je vous le promets." 

Une chose importante à noter dans le code ci-dessus est l'appel du résoudre et rejeter les fonctions. Rappelez-vous que ceci est notre façon de dire à notre promesse que notre code a été exécuté ou non. Sinon, on ne saura jamais.

En utilisant le même code que dans notre exemple de base, nous pouvons voir comment notre demande AJAX dans la promesse va maintenant fonctionner.

// Dites à notre promesse d'exécuter son code // et dites-nous quand c'est fait. myPromise.then (function (result) // Imprime JSON reçu sur la console. console.log (result);, function (result) // Imprime "Aww n'a pas fonctionné" ou // "Page chargée, mais status not OK. "console.error (result););

Je savais que nous pouvions te faire confiance, ma promesse.

Enchaînement des promesses

Maintenant, vous pensez peut-être à ce stade que les promesses ne sont que des fonctions de rappel sophistiquées avec une syntaxe plus agréable. Cela est vrai dans une certaine mesure, mais pour continuer avec notre exemple AJAX, supposons que vous deviez faire quelques requêtes supplémentaires, chaque requête étant basée sur le résultat de la dernière. Ou si vous deviez d'abord traiter le JSON? 

Faire cela avec des rappels aboutirait à une imbrication lourde de fonctions, chacune d’elles devenant de plus en plus difficile à suivre. Heureusement, dans le monde des promesses, nous pouvons enchaîner de telles fonctions ensemble. Voici un exemple où, lorsque nous recevons le JSON pour le commentaire d'un utilisateur sur notre faux blog, nous voulons nous assurer que tout est en minuscule avant de faire autre chose..

myPromise .then (function (result) // Dès que nous avons reçu JSON, // le transformons en objet JSON et le retourne. renvoie JSON.parse (result);) .then (function (parsedJSON) // Une fois que json a été analysé, // récupère l'adresse e-mail et la met en minuscule. Renvoie parsedJSON.email.toLowerCase ();) .then (function (emailAddress) // Une fois le texte inséré, // affiche-le sur la console. console.log (emailAddress);, function (err) // Quelque chose dans la chaîne ci-dessus a mal tourné? // Imprimer la sortie rejetée. console.error (err););

Vous pouvez voir ici que même si notre appel initial était asynchrone, il est également possible de chaîner des appels synchrones. Le code dans chaque résoudre fonctionner à l'intérieur du puis sera appelé quand chacun reviendra. Vous remarquerez également qu'il n'y a qu'une seule fonction d'erreur spécifiée ici pour toute la chaîne. En plaçant ceci à la fin de la chaîne en tant que rejeter fonctionner dans le dernier puis, toute promesse dans la chaîne qui appelle rejeter appellera celui-ci.

Maintenant que nous avons un peu plus confiance en nos promesses, créons-en une autre en conjonction avec celle ci-dessus. Nous en créerons un qui prend notre nouvelle adresse e-mail en minuscule et nous (prétendons) envoyer un e-mail à cette adresse. Ceci est juste un exemple pour illustrer quelque chose d'asynchrone - cela peut être n'importe quoi, comme contacter un serveur pour voir si l'email était sur une liste blanche ou si l'utilisateur est connecté. Nous devrons donner l'adresse email à la nouvelle promesse, mais les promesses n'acceptent pas les arguments. Le moyen de contourner cela est d’envelopper la promesse dans une fonction qui, comme ceci:

var sendEmail = function (emailAddress) retourne une nouvelle promesse (function (resolir, rejeter) // Prétendre l'envoi d'un email // ou faire autre chose de manière asynchrone setTimeout (function () resol ('Email envoyé à' + emailAddress); , 3000);); ;

Nous utilisons le setTimeout appeler ici pour simuler simplement une tâche qui prend quelques secondes pour s'exécuter de manière asynchrone.

Alors, comment utilisons-nous notre nouvelle fonction de création de promesse? Eh bien, puisque chaque résoudre fonction utilisée dans un puis devrait renvoyer une fonction, nous pouvons l'utiliser de la même manière que nos tâches synchrones.

myPromise .then (fonction (résultat) return JSON.parse (résultat);) .then (fonction (parsedJSON) return parsedJSON.email.toLowerCase ();) .then (fonction (emailAddress) return sendEmail (emailAddress )) .then (function (result) // Outputs "Email envoyé à [email protected]" console.log (result);, function (err) console.error (err););

Passons en revue ce flux simplement pour résumer ce qui se passe. Notre promesse initiale ma promesse demande un morceau de JSON. Lorsque ce JSON est reçu (nous ne savons pas quand), nous le transformons en objet JavaScript et renvoyons cette valeur.. 

Une fois que cela est fait, nous extrayons l'adresse e-mail du fichier JSON et nous la mettons en minuscule. Ensuite, nous envoyons un e-mail à cette adresse, mais nous ne savons pas encore quand il sera terminé, mais si c'est le cas, nous enverrons un message de réussite à la console. Aucune nidification lourde en vue.

Conclusion

J'espère que cela a été une introduction utile à Promises et qu'il vous a donné une bonne raison de commencer à les utiliser dans vos projets JavaScript. Si vous voulez en savoir plus sur Promises, consultez l'excellent article HTML5 Rocks de Jake Archibald sur ce sujet..

Apprendre JavaScript: le guide complet

Nous avons créé un guide complet pour vous aider à apprendre le JavaScript, que vous soyez débutant en tant que développeur Web ou que vous souhaitiez explorer des sujets plus avancés..