javascript tome xxiii promises - async - await
Transcription
javascript tome xxiii promises - async - await
PETITE INTRODUCTION À PROMISE (PROMESSES), Async / await J AVA S C R I P T (Programmation Internet) VOL. XXIII J.B. Dadet DIASOLUKA Luyalu Nzoyifuanga +243 - 851278216 - 899508675 - 995624714 - 902263541 - 813572818 [email protected] I. PETITE INTRODUCTION à PROMISE : L'objet "Promise" (EcmaScript 6, 2015), facilite la programmation asynchrone. Les opérations asynchrones (chronologiquement dépendantes entre elles et qui doivent attendre l’une le parachèvement du précédent (pour exécuter en fonction du résultat que la précédente renverra à la suivante), pendant que les autres opérations indépendantes de la chaîne des opérations asynchrones continuent leur processus. On parle de « fonctionnement non bloquant ». Les « Promise » sont TOUJOURS asynchrones. Le modèle de base d’une fonction promise est le suivant : <script type="text/javascript"> "use strict"; function asyncFunc() { return new Promise( function (resolve, reject) { ··· resolve(data); ··· reject(error); }); } </script> J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Et son appel se fait comme suit : asyncFunc() .then(result => { ··· }) .catch(error => { ··· }); .finally(result | error => { ··· }); Une syntaxe minimaliste d’une Promise. Remarquez que « . finally » s’exécute pourtant avant le « . then » et le « . catch » : <script type="text/javascript"> "use strict"; Promise.resolve("Résolue") .then (r => console.log(r)) .catch (r => console.log(r)) .finally (console.log("Finally")); </script> <script type="text/javascript"> "use strict"; Promise.reject("Rejeté") .then (r => console.log(r)) .catch (r => console.log(r)) .finally (console.log("Finally")); </script> « Promise » en tant que « objet » émettant des « events » (« event emitter ») : <script type="text/javascript"> "use strict"; console.log("/* I. EVENT EMITTER - RÉUSSITE */"); function asyncFuncEchec() { const eventEmitter = { reussi: [] , echec: [] }; Promise-Promesse & async-await -2/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu // Hash ayant 2 Arrays vides JavaScript Tome-XXIII setTimeout(() => { for (const i of eventEmitter.echec) { i('Timeout dépassé'); } }, 5000); // 5 secondes return eventEmitter; // Retourne « eventEmitter = { reussi: [] , echec: [] } » } // Appel fonction asynFunc var r = asyncFuncEchec(); r.echec.push(x => console.log('Dommage : '+x)); // Au final : Timeout dépassé console.log(r["reussi"]); // Array [ () ] console.log(r); // Object { reussi: (1) […] } ////////////////////////////////////////////////// console.log("\n\n/* II. EVENT EMITTER - ÉCHEC */"); ////////////////////////////////////////////////// function asyncFuncReussite() { const eventEmitter = { reussi: [] , echec: [] }; // Hash ayant 2 Arrays vides setTimeout(() => { for (const i of eventEmitter.reussi) { i('Timeout accpmpli'); } }, 1000); // 1 seconde return eventEmitter; // Retourne « eventEmitter = { reussi: [] , echec: [] } » } // Appel fonction asynFunc var r = asyncFuncReussite(); r.reussi.push(x => console.log('\nParfait : '+x)); // Au final : Timeout dépassé Promise-Promesse & async-await -3/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII console.log(r["reussi"]); // Array [ () ] console.log(r); // Object { reussi: (1) […] } </script> Avec Firefox 64.0b13 : Promise-Promesse & async-await -4/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Avec Yandex Version 18.11.1.385 beta : Promise-Promesse & async-await -5/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Promise-Promesse & async-await -6/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII « Promise » utilisé directement : Voir page 22 ci-dessous : Un petit programme de base pour utiliser les Promises.. Promise-Promesse & async-await -7/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII L’objet Promise permet un certain degré de multithreading dans ce sens que le déroulement des autres parties du programme se poursuit pendant que les opérations asynchrones s’enchaînent aussi (accès au réseau ou au disque, chargement d’une page Web, remplissage de formulaires, communiquer avec les travailleurs [du web ou du service], timer, requêtes AJAX..:. Certaines opérations n’ont aucune préoccupation les unes des autres sur leur état d’exécution, pour démarrer ou poursuivre leur propre exécution. C’est le multithreading : que l’on retrouve facilement avec le setTimeout ou le setInterval. EXEMPLE 1 : Fonction asynchrone. Avec « Promise() » : <script type="text/javascript"> "use strict"; let fProcess = () => { console.log("Dans fProcess()"); let n = 10000000000; let st = new Date(); for(let i=0 ; i<n ; i++); let et = new Date(); /**/ /**/ /**/ /**/ /**/ /**/ /**/ /**/ return new Promise( (resolve, reject) => { console.log("* Dans Promise avant resolve *"); resolve(" Fini l'attente de " + (et - st) / 1000 + ` secondes pour ${n.toExponential(2)} cycles.`) } ); }; async function fAsync() { console.log("! Preparing to await !"); Promise-Promesse & async-await -8/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu let r = await fProcess(); console.log("! Fini le await !"); return "x".repeat(5) + r; } JavaScript Tome-XXIII console.log("Entry point" .padStart(16,".") .padEnd(21,".")); fAsync() . then(function(res) { console.log(res); console.log("La FIN" .padStart(11,"=") .padEnd(16,"=")); }) console.log("La suite..."); </script> Sans promise, la succession est la même, mais ce code ne permettra pas une action en cas de « reject » : <script type="text/javascript"> "use strict"; let fProcess = () => { console.log("Dans fProcess()"); let n = 10000000000; let st = new Date(); for(let i=0 ; i<n ; i++); Promise-Promesse & async-await -9/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu let et = new Date(); /**/ /**/ /**/ JavaScript Tome-XXIII return (" Fini l'attente de " + (et - st) / 1000 + ` secondes pour ${n.toExponential(2)} cycles.`) }; async function fAsync() { console.log("! Preparing to await !"); let r = await fProcess(); console.log("! Fini le await !"); return "x".repeat(5) + r; } console.log("Entry point" .padStart(16,".") .padEnd(21,".")); fAsync() . then(function(res) { console.log(res); console.log("La FIN" .padStart(11,"=") .padEnd(16,"=")); }) console.log("La suite..."); </script> 21:04:25,063 21:04:25,065 21:04:25,066 21:04:38,083 21:04:38,084 21:04:38,084 21:04:38,085 .....Entry point..... test.html:25:1 ! Preparing to await ! test.html:18:5 Dans fProcess() test.html:3:5 La suite... test.html:37:1 ! Fini le await ! test.html:20:5 xxxxx Fini l'attente de 13.015 secondes pour 1.00e+10 cycles. test.html:31:9 =====La FIN===== test.html:32:9 Pour voir l’effet de « await », « async » et « Promise » nous allons ci-après désactiver tout ce qui se rapporte à eux : Promise-Promesse & async-await -10/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII <script type="text/javascript"> "use strict"; let fProcess = () => { console.log("Dans fProcess()"); let st = new Date(); for(let i=0 ; i<1000000000 ; i++); let et = new Date(); console.log( "Fini l'attente de "+ (et-st)/1000 + " secondes." ); }; let res; /* async */ function fAsync() { console.log("! Preparing to await !"); /* await */ fProcess(); res = "x".repeat(5); } console.log("...Entry point"); fAsync() // . then(function(res) { console.log(res); // }) console.log("La suite..."); </script> Exécutioin : 21:17:43.212 21:17:43.216 21:17:43.217 21:17:44.511 21:17:44.511 21:17:44.511 test.html:22 ...Entry point test.html:16 ! Preparing to await ! test.html:3 Dans fProcess() test.html:7 Fini l'attente de 1.294 secondes. test.html:26 xxxxx test.html:29 La suite... . ! . Attention . ! . Promise-Promesse & async-await -11/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Si le processus à attendre est la fonction window.setTimeout() les choses se passent aussi tout différemment ! <script type="text/javascript"> "use strict"; let fProcess = (function(d,st) { setTimeout(function () { console.log("Dans fProcess()"); console.log( "Fini l'attente de "+ (new Date()-st)/1000 + " secondes." ); }, d*1000)}); async function fAsync(p) { console.log("! Preparing to await !"); await fProcess(p,new Date()); return "x".repeat(5); } console.log("...Entry point"); fAsync(3) . then(function(res) { console.log(res); }) console.log("La suite..."); </script> 21:40:38.326 21:40:38.330 21:40:38.331 21:40:38.331 21:40:41.335 21:40:41.336 test.html:19 ...Entry point test.html:13 ! Preparing to await ! test.html:26 La suite... test.html:23 xxxxx test.html:3 Dans fProcess() test.html:4 Fini l'attente de 3.005 secondes. Promise-Promesse & async-await -12/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Dans le point d’entrée de l’exécution de ce code : fAsync(3) . then(function(res) { console.log(res); }) res prend automatiquement la valeur (« xxxxx ») retournée par async function fAsync(p) { console.log("! Preparing to await !"); await fProcess(p,new Date()); return "x".repeat(5); } Mais bien avant ça, le contrôle du programme est passé à la fonction async function fAsync(p) {} Mais pendant que la fonction async fAsync() se débat, il continue avec les instructions qui viennent après dont celle : console.log("La suite..."); qui évidemment affiche "La suite...". Dans l’entre-temps dans async function fAsync(p) {} pendant qu’il attent le delai imparti par let fProcess = (function(d,st) { setTimeout(function () {} il poursuit avec l’instruction qui suit; return "x".repeat(5); Promise-Promesse & async-await -13/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII l’appelant sleep(3) qui à qui renvoie sa valeur de retour "xxxx" à son tour la renvoie à la méthode .then qui à son tour la renvoie à son paramètre res et l’affiche avec l’instruction console.log(res). fAsync(3) . then(function(res) { console.log(res); }) Pendant ce temps, « setTimeout » continue sa décompte à partir du nombre de millisecondes impartis, et à zéro il exécutera console.log( "Fini l'attente de "+ (new Date()-st)/1000 + ); " secondes." Une façon simple d’utiliser « setTimeout » dans une « Promise » : <SCRIPT> "use strict"; function temporiser(s) { console.log("Dans temporiser"); /**/ /**/ /**/ /**/ /**/ return new Promise( function (resolve, reject) { setTimeout(resolve, s*1000); } ); } let d=5, st=new Date(); console.log(`Attente de ${d} secondes`); /**/ /**/ /**/ /**/ /**/ temporiser(5).then(function () { console.log( `${(new Date() - st)/1000} secondes passées` ); }); Promise-Promesse & async-await -14/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII console.log("La suite pdt attente..."); </SCRIPT> Mais comment faire si on voudrait par exemple que la chaîne affichée par l’instruction dans notre fonction async ci-dessus soit plutôt retournée à l’appelant, ni await ni async ne pouvant le faire ? C’est là que Promise devient indispensable. Soit, passons. Une autre façon d’utiliser await et async : <script type="text/javascript"> "use strict"; let d; function retarder(delai){ d = new Date(); return new Promise(function(resolve) { setTimeout(function () { resolve() }, delai*1000); }) } async function go(p) { console.log("En pause de "+p+" secondes..."); await retarder(p) Promise-Promesse & async-await -15/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII return ((new Date()-d)/1000)+" secondes révolues" } go(2).then(function(retVal) { console.log(retVal); }) </script> Exécution : En pause de 2 secondes... test.html:26 2.013 secondes révolues Voici un modèle de base très simple de Promise : <script type="text/javascript"> "use strict"; Promise .resolve("Promesse Résolue") .then(x => console.log(x)); // => Promesse Résolue Promise .reject("Promesse Rejetée") .catch(x => console.log(x)); // => Promesse Rejetée </script> Mais en fait,« . then » ou « . catch », c’est plus votre propre affaire que de n’importe quoi d’autre, d’autant plus que c’est vous qui tranchez sur la réussite ou l’échec, au point que si vous le voulez, vous pouvez utiliser « . then » à la place de « . catch » et vice versa. Mais pour une meilleure clarté de la logique du code, il faut respecter les principes. Le moyen le plus sûr de retourner un échec est de renvoyer une exPromise-Promesse & async-await -16/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII ception avec « throw » (qui n’est pas une méthode mais un opérateur du genre « return »). L’opérateur « return » retourne (= met fin à l’exécution de [ou quitte] la fonction en cours) éventuellement en renvoyant le résultat d’une expression qui peut bien aussi être substituée par un scalaire, tandis que toute valeur retournée par « throw » est considérée comme une exception (signalement d’erreur). 1ère version (exploitation sélective de « resolve » et « reject »). Notez que la « réussite » est gérée par « résolve » à la ligne 13, et l’échec par « reject » à la ligne 16 : <script type="text/javascript"> "use strict"; var r; let pr = new Promise(function(resolve , reject) { (r = (Math.random()*10)) > 5 ? resolve(r+" > 5") : reject(new Error(r+" <= 5")) }); pr .then(function(res){ console.log(res); }) .catch(function(rej){ console.log(rej); }) .finally(function(res,rej){ console.log(`** Qq soit l'issu de promise`); console.log(`res = ${res} , ` , "rej = ",rej); }); console.log("La suite ... Patientez ~"); </script> Promise-Promesse & async-await -17/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII 2ème version (exploite « resolve » à la place de « reject »). Notez que les deux états (réussite et échec) sont exécutés par la même « resolve » de la ligne 13 : <script type="text/javascript"> "use strict"; var r; let pr = new Promise(function(resolve) { (r = (Math.random()*10)) > 5 ? resolve(r+" > 5") : resolve(new Error(r+" <= 5")) }); pr .then(function(res){ console.log(res); }) .catch(function(rej){ console.log(rej); }) .finally(function(res,rej){ console.log(`** Qq soit l'issu de promise`); console.log(`res = ${res} , ` , "rej = ",rej); }); console.log("La suite ... Patientez ~"); </script> Promise-Promesse & async-await -18/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII 3ème version (exploite « throw »). Notez que quand « reason » ne s’affiche pas dans une chaîne unique concaténée, mais seulement quand les éléments à afficher sont dissociées (séparés par une virgule dans l’instruction « console . log ( ) ») : <script type="text/javascript"> "use strict"; new Promise(function(resolve,reject){ resolve(new Error("in Promise")); // * Si resolve => .then() s'exécute d'abord. // * Si reject => .catch() s'exécute // directement après. }) .then(function (value) { /**/ throw new Error(`« ${value} , & in then() " »`); }) .catch(function (reason) { console.log(`${reason}, in .catch()`); console.log(reason + ", in .catch()"); console.log(reason," in .catch()"); }); </script> Avec Firefox : Promise-Promesse & async-await -19/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Avec Yandex : Dans le cas où la « Promise » appelée n’exécute ni « resolve » ni « reject » mais « null », même « . finally » n’est pas exécutée ! <script type="text/javascript"> "use strict"; var r; let pr = new Promise(function(resolve) { (r = (Math.random()*10)) <= 5 ? resolve(new Error(r+" <= 5")) : null; }); pr .then(function(res){ console.log(res); }) .catch(function(rej){ console.log(rej); }) .finally(function(res,rej){ console.log(`** Qq soit l'issu de promise`); console.log(`res = ${res} , ` , "rej = ",rej); }); console.log("La suite ... Patientez ~"); </script> Si Échec : émet un message d’erruer. Promise-Promesse & async-await -20/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Si Réussite : ne déclenche aucune action. Si la « Promise » appelée retourne « null » comme valeur de retour, « . finally » est exécutée, mais la méthode correspondante (« . then » ou « . catch », ici « . catch ») ne sera jamais executée ! Si la méthode gérant la « Promise » appelée (« . then » ou « . catch ») utilise « null » comme paramètre au lieu d’un autre nom c’est-à-dire quand elles utilisent « null » à la place de la valeur retournée par la « Promise » appelée), alors « . finally » est aussi exécutée, mais la valeur retournée par la « Promise » appelée sera remplacée par « null » ! Dans l’exemple qui suit, si le nombre aléatoire généré est supérieur à 5, il y a une réussite gérée par « reject » qui renvoie « null ». Si l’aléatoire généré est inf ou égal à 5, il y a échec (erreur) gérée par « resovle » qui utilisera « null » à la place de la valeur de retour. <script type="text/javascript"> "use strict"; var r; let pr = new Promise(function(resolve) { (r = (Math.random()*10)) <= 5 ? resolve(new Error(r+" <= 5")) : reject(null); Promise-Promesse & async-await -21/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu }); JavaScript Tome-XXIII pr .then(null, error => { console.log("Dans « .then(null...) »"); console.log(null); }) .catch(rej => { console.log( "Dans « .catch() recevant « null »)" , "Ce « .catch() » ne sera jamais exécuté)" ); console.log(rej) }) .finally(function(res,rej){ console.log(`** Qq soit l'issu de Promise`); console.log(`res = ${res} , ` , "rej = ",rej); }); console.log("La suite ... Patientez ~"); </script> EXEMPLE 2 : Un petit programme de base pour utiliser les Promises. Promise-Promesse & async-await -22/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII <script type="text/javascript"> "use strict"; var r; let pr = new Promise(function(resolve , reject) { (r = (Math.random()*10)) > 5 ? resolve(r+" > 5") : reject(new Error(r+" <= 5")) }); pr .then(function(res){ console.log(res); }) .catch(function(rej){ console.log(rej); }) .finally(function(res,rej){ console.log(`** Qq soit l'issu de promise`); console.log(`res = ${res} , ` , "rej = ",rej); }); console.log("La suite ... Patientez ~"); </script> Exécution : Firefox Quantum 64.0b13 : Promise-Promesse & async-await -23/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Yandex Version 18.11.1.385 beta : EXEMPLE 3 : C’est plus clair comme ceci, donc plus facile à déboguer = comprendre et entretenir : <script type="text/javascript"> "use strict"; var r; let fresolve = res => console.log(res); var freject = rej => console.log(rej); const callback = (resolve , reject) => { (r = (Math.random()*10)) > 5 ? resolve(r+" > 5") : reject(r+" <= 5") } let pr = new Promise(callback); pr . then(fresolve) . catch(freject); Promise-Promesse & async-await -24/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII console.log("La suite ... Patientez ~"); </script> Exécution : La suite ... Patientez ~ 8.956280132591708 > 5 test.html:26:3 test.html:6:25 La suite ... Patientez ~ 1.4543918018972757 <= 5 test.html:26:3 test.html:8:24 Vous pouvez définir la Promise dans une fonction qui la retourne. <script type="text/javascript"> "use strict"; let fresolve = res => console.log(res); var freject = rej => console.log(rej); let f = _ => { var r; return new Promise( function(resolve , reject) { (r = (Math.random()*10)) > 5 ? resolve(r+" > 5") : reject(r+" <= 5") } ) } let pr = f() pr . then(fresolve) . catch(freject); Promise-Promesse & async-await -25/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII console.log("La suite ... Patientez ~"); </script> Exécution : La suite ... Patientez ~ 6.383279223571002 > 5 > 5 test.html:29:3 test.html:3:25 La suite ... Patientez ~ 2.9502974244747504 <= 5 test.html:29:3 test.html:5:24 Sachez que les méthodes .then et .catch sont aussi des Promises. Leur callback (fonction-argument) reçoit la valeur retournée par la promise précédente (soit le corps de la définition de la Promise, soit une autre .then ou .catch). Chaque méthode .then ou .catch retourne aussi une valeur au paramètre de la .then ou .catch qui sera exécutée après elle. « .catch » gère les erreurs de tous les « then » qui le précèdent. Vérification avec « Promise » si un nombre est divisible par 100 aléatoires et si ces aléatoires ne sont pas zéro : <script type="text/javascript"> "use strict"; const c=Math.round(Math.random()*100); var diviseurs = () => new Promise((ok, ko) => { var aleat = Math.round(Math.random() * c); if (aleat > 0) { let ast=""; var result = c / aleat; if(!(result%1))ast="*".repeat(5) ok({aleat, result, ast}); } else { ko(new Error("Division par 0!")); } Promise-Promesse & async-await -26/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu }); JavaScript Tome-XXIII let cptr=0; let int = setInterval(() => diviseurs() . then((data) => { // Si OK console.log(++cptr+". "+c," divisé par", data.aleat, "=", data.result, data.ast); if(cptr==100)clearInterval(int); }) . catch((err) => { // Si erreur console.log(err); }) , 100 /* à intervalle régulier (1/10e sec). */); </script> 1. 76 divisé par 19 = 4 ***** test.html:25:13 2. 76 divisé par 44 = 1.7272727272727273 test.html:25:13 3. 76 divisé par 1 = 76 ***** test.html:25:13 4. 76 divisé par 49 = 1.5510204081632653 test.html:25:13 5. 76 divisé par 5 = 15.2 test.html:25:13 6. 76 divisé par 38 = 2 ***** test.html:25:13 7. 76 divisé par 23 = 3.3043478260869565 test.html:25:13 … 60. 76 divisé par 21 = 3.619047619047619 test.html:25:13 Error: "Division par 0!" Diviseurs file:///K:/DADET/PROGS/test.html:14:12 diviseurs file:///K:/DADET/PROGS/test.html:4:23 int file:///K:/DADET/PROGS/test.html:22:9 test.html:31:13 61. 76 divisé par 27 = 2.814814814814815 test.html:25:13 62. 76 divisé par 36 = 2.111111111111111 test.html:25:13 … 98. 76 divisé par 44 = 1.7272727272727273 test.html:25:13 99. 76 divisé par 35 = 2.1714285714285713 test.html:25:13 100. 76 divisé par 40 = 1.9 test.html:25:13 Avec Yandex : test.html:31 Error: Division par 0! Promise-Promesse & async-await -27/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu at at at at Promise new Promise diviseurs setInterval JavaScript Tome-XXIII (test.html:14) (<anonymous>) (test.html:4) (test.html:22) C’est préférable de retourner la valeur d’une .then ou d’une .cath avec la directive return., mais celle du corps de la Promise avec seulement resolve ou reject. 1. « resolve » est le « return » d’un objet « Promise » quand l’opération asynchrone a réussi, avec la valeur que vous lui donnez, qui sera récupérée par la première « . then » rencontrée. 2. « reject » est le « return » d’un objet « Promise » quand l’opération asynchrone n’a pas réussi, de préférence en appelant l’instruction « new Error ("votre msg Échec"); » (le message d’erreur lui est spécifié en argument). Cette valeur retournée traversera toutes les « . then » jusqu’à rencontrer le premier « . catch » <script type="text/javascript"> "use strict"; let delai = 15000; let pr = new Promise(function(resolve) { console.log("En plein dedans dans la Promise"); setTimeout(function () { resolve("Promise résolue ") }, delai); }); console.log(pr); let d=new Date(); pr.then(function(resolve){ console.log("dans le 1er .then"); return resolve + "En ~" }).then(function(resolve){ Promise-Promesse & async-await -28/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu console.log("dans le 2è .then"); return resolve; }).then(function(resolve){ console.log("dans le 3è .then"); let t = (new Date()-d)/1000; console.log(resolve+t+" secs."); }); JavaScript Tome-XXIII console.log( "La suite ... Patientez ~"+delai/1000+" secs."); </script> Exécution : Notez l’ordre d’exécution, et que les instructions qui devraient être exécutées après la Promise ont exécuté avant que toute la chaîne de Promise finisse son exécution. Avec Firefox : En plein dedans dans la Promise test.html:4:5 Promise { <state>: "pending" } test.html:10:1 <state>: "pending" <prototype>: PromiseProto { … } catch: function catch() constructor: function Promise() finally: function finally() then: function then() Symbol(Symbol.toStringTag): "Promise" <prototype>: Object { … } La suite ... Patientez ~15 secs. dans le 1er .then dans le 2è .then dans le 3è .then Promise résolue En ~15.001 secs. test.html:26:1 test.html:15:3 test.html:18:5 test.html:21:5 test.html:23:5 Avec Yandex : test.html:10 test.html:10 En plein dedans dans la Promise Promise {<pending>} Promise-Promesse & async-await -29/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII __proto__: Promise catch: ƒ catch() constructor: ƒ Promise() finally: ƒ finally() then: ƒ then() Symbol(Symbol.toStringTag): "Promise" __proto__: Object [[PromiseStatus]]: "resolved" [[PromiseValue]]: "Promise résolue " test.html:26 La suite ... Patientez ~15 secs. test.html:15 dans le 1er .then test.html:18 dans le 2è .then test.html:21 dans le 3è .then test.html:23 Promise résolue En ~14.999 secs. Voici l’exécution de notre programme ci-dessus sans Promise. Il exécute exactement de la même façon. Rappelez-vous que setTimeout (function_callback , delai); et setInterval (function_callback , delai); permettent aussi des opérations asynchrones : « on ne peut pas poursuivre l’exécution [ de ceci ] sans que le délai imparti ne soit atteint ». « setTimeout() » a été utilisée ici seulement pour simuler l’attente d’un signal d’un port de communication par exemple. Tester avec « Promise ( ) » si une année et bissextile : <SCRIPT> "use strict"; function asyncFunc1(annee) { console.log(annee); return new Promise( function (resolve, reject) { let b=!(annee%4) && (!(annee%400) || (annee%100)); if(b)resolve(b); reject(new Error("Dans asyncFunc1")); Promise-Promesse & async-await -30/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu }); } JavaScript Tome-XXIII let a=Math.round(Math.random()*2100); asyncFunc1(a) .then(resolvAsynFunc1 => { return resolvAsynFunc1; }) .then(resThen => { console.log(a," => ",resThen," Année Bisextile"); }) .catch(error => { console.log(new Error(error+" : Non Bissextile")); }); </SCRIPT> Ce même programme en « Queue de Promise » : <SCRIPT> "use strict"; function asyncFunc1(annee) { console.log(`Année « ${annee} » :`); Promise-Promesse & async-await -31/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII return new Promise( function (resolve, reject) { let b = !(annee%4) && (!(annee%400) || (annee%100)); if(b){ // TRAITEMENT PRÉLIMINAIRE console.log( "Sucess in PRETREATMENT in "+ "asyncFunc1().resolve()"); resolve(b); } throw new Error( // TRAITEMENT PRÉLIMINAIRE ? // Tout est retourné comme String. _ => { console.log("PRETREATMENT « throw » : "+ "NonBisex, "+ "in asyncFunc1().throw()"); return ("Done in asyncFunc1().throw()"); } ) }); } let a=Math.round(Math.random()*2100); let fAsync = asyncFunc1(a); // TRAITEMENTS APPROFONDIS. fAsync.then(resolvAsynFunc1 => { return resolvAsynFunc1; }) .then(resThen => { console.log(a," => ",resThen, " Année Bisextile (FULL TREATMENT)"); }) .catch(error => { console.log(new Error(error + " : Non Bissextile (FULL TREATMENT)")); }); </SCRIPT> Promise-Promesse & async-await -32/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Avec Firefox : Avec Yandex : Chaînage de « Promises » : Mais à elles seules, il n’est pas possible de chaîner facilement [et surtout clairement] en une seule instruction, les opérations qui doivent nécessairement s’attendre l’une l’autre, et le codage devient lourd et confus. Promise-Promesse & async-await -33/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII <script type="text/javascript"> "use strict"; let delai = 15000; // let pr = new Promise(function(resolve) { console.log("Ici on était dans la Promise"); setTimeout(function () { f("La Promise était résolue ici") }, delai); // }); // console.log(pr); let d=new Date(); // pr.then(function(resolve){ function f(resolve){ console.log("Ici était le 1er .then"); f1(resolve + " En ~"); } // }).then(function(resolve){ function f1(resolve){ console.log("Ici était le 2è .then"); f2(resolve); // }).then(function(resolve){ } function f2(resolve){ console.log("Ici était le 3è .then"); let t = (new Date()-d)/1000; console.log(resolve+t+" secs."); } // }); console.log( "La suite ... Patientez ~"+delai/1000+" secs."); </script> Voici l’exécution de ce programme sans Promise et sans setTimeout <script type="text/javascript"> "use strict"; let delai = 15000; let d=new Date(); // let pr = new Promise(function(resolve) { Promise-Promesse & async-await -34/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII console.log("Ici on était dans la Promise"); // setTimeout(function () { f("La Promise était résolue ici") // }, delai); // }); // console.log(pr); // pr.then(function(resolve){ function f(resolve){ console.log("Ici était le 1er .then"); f1(resolve + " En ~"); } // }).then(function(resolve){ function f1(resolve){ console.log("Ici était le 2è .then"); f2(resolve); // }).then(function(resolve){ } function f2(resolve){ console.log("Ici était le 3è .then"); let t = (new Date()-d)/1000; console.log(resolve+t+" secs."); } // }); console.log( "La suite ... Patientez ~"+delai/1000+" secs."); </script> Exécution : Le programme a cette fois-ci exécuté sans aucun délai quelque part : Ici on était dans la Promise test.html:6:5 Ici était le 1er .then test.html:16:5 Ici était le 2é .then test.html:22:5 Ici était le 3é .then test.html:28:5 La Promise était résolue ici En ~0.001 secs. test.html:30:5 La suite ... Patientez ~15 secs. test.html:34:1 Promise-Promesse & async-await -35/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Pour mieux se figurer une Promise, ça rappelle dans une certain mesure l’instruction inkey$ de notre beau vieux GW-Basic du MS-DOS, et la commande PRINT de la ligne de commande du MS-DOS qui imprime le document proposé, pendant que toutes les autres tâches continuent à se dérouler comme si rien n’était. Chaînage de Promises 2 : <SCRIPT> "use strict"; function asyncFunc2() { return new Promise( function (resolve, reject) { //resolve("Réussi asyncFunc2"); reject(new Error("Reject in asyncFunc2")); }); } function asyncFunc1() { return new Promise( function (resolve, reject) { resolve("Réussi asyncFunc1"); reject(error); }); } asyncFunc1() .then(resolvAsynFunc1 => { console.log(resolvAsynFunc1); return asyncFunc2(); }) .then(resolvAsynFunc2 => { console.log(resolvAsynFunc2); }) .catch(error => { console.log(error); }); </SCRIPT> Promise-Promesse & async-await -36/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII En libérant l’instruction //resolve("Réussi asyncFunc2"); dans function (resolve, reject) { resolve("Réussi asyncFunc2"); reject(new Error("Reject in asyncFunc2")); }); Devions un peu, voici un pseudo polyfill simulant le inkey$ de GWBasic. (UP + CUMUL)<br>Tapez un caractère <input id="u" onkeyup="f(value)"> <br><br>(DOWN)<br>Tapez un caractère <input id="d" onkeydown="f2(value)"> <br><br>(PRESS)<br>Tapez un caractère <input id="p" onkeypress="f3(value)"> <script type="text/javascript"> "use strict"; function f(p){ console.log(p); console.log(document.getElementById('u').value); } function f2(p){ console.log(p); Promise-Promesse & async-await -37/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII console.log(document.getElementById('d').value); document.getElementById('d').value="" } function f3(p){ console.log(p); console.log(document.getElementById('p').value); document.getElementById('p').value="" } </script> Exécution de ce polyfill : I. Notez que « onkeyup » prend ici le texte de la fenêtre « input » juste APRÈS avoir relâché la dernière touche, donc le texte que vous venez juste de taper. II. Notez que « onkeydown » prend ici la valeur (texte) qui était dans la fenêtre « input » AVANT d'avoir tapé la dernière touche, et non pas après l’avoir tapée. III. Notez que « onkeypress » aussi, prend ici la valeur (texte) qui était dans la fenêtre « input » AVANT d'avoir tapé la dernière touche, et non pas après l’avoir tapée. Ceci, sûrement parce que le système d'exploitation lit la zone quand la touche est relâchée, alors que « onkeydown » et « onkeypress » lisent la zone juste au moment où la touche est appuyée. « onkeydown » et « onkeypress » serviraient bien sans problèmes pour la touche <RETURN> de validation, tandis que « onkeyup » servirait mieux pour lire la prochaine touche qu’on attend à appuyer. Les Promises (promesses) avaient longtemps été utilisées dans les librairies telles que Q, when, WinJS, RSVP.js... Promise-Promesse & async-await -38/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Revenons à nos moutons… Comme tout objet, les objets Promise se créent avec l’opérateur « new ». L’objet Promise peut fonctionner en mode « use strict » ou pas. L’objet Promise attend qu’une action ou un événement asynchrone s’achève pour appeler une deuxième fonction (outre celle qu’elle renferme), les deux fonctions étant liées avec le mot-clé « then ». La fonction asynchrone retourne son résultat à l’objet Promise, et Promise passe cette valeur de retour [comme paramètre] à la fonction désignée par then qui elle-même servira de Promise si elle aussi est suivie de then. THEN = Si la tâche qui précède s’achève ALORS exécutez (passez à) cette fonction qui suit, avec comme argument la valeur retournée par la précédente qui se comporte aussi comme une Promise. Le principe de définition d’une Promise est le suivant : Promise prend UN et un seul argument obligatoire, sa fonction callback. Cette fonction callback est : soit une définition compète de fonction (pouvant aussi être une fonction fléchéie), sot un pointeur sur cette fonction. Elle prend deux arguments facultatifs : Le premier est le code à exécuter si la Promise a été une réussite, le deuxième est le code à exécuter si la Promise n’a pas satisfait, celle exécutée retourne une valeur au premier .then ou .catch qui vient après l’appel de la Promise. La valeur retournée par Promise est captée par le paramètre-fonction callback de .then ou de .catch. Bien entendu, les deux fonctions callback (paramètres de la fonction Callback de Promise et qui sont souvent représentées par des pointeurs_sur_fonction représentant « resolve » et « reject ») sont optionnelles : soit seulement le premier (« resolve ») pour tester un résultat Promise-Promesse & async-await -39/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII concluant, soit seulement le deuxième (« reject ») pour tester un échec (le contraire de votre voeu). Si vous jugez qu’il faut seulement le sempiternel deuxième paramètre (« reject ») mais que le premier paramètre (« resolve ») ne doit absolument pas figurer il faut alors baptiser ce premier paramètre « undefined » (sans guillemets) ; on ne peut pas laisser à vide la place du premier paramètre (première fonction callback). Mais il n’y a pas grand inconvénient de laisser le premier paramètre même dans le cas où il n’est pas utile/utilisé. En fait, « resolve » et « reject » sont des pointeurs sur des méthodes de l’objet « Promise » et peuvent en principe être appelées n’importe comment pour autant qu’ils respectent leur emplacement. <script type="text/javascript"> "use strict"; function asyncFunc(a) { return new Promise( function (ndima, bwaka) { if(a == 5) ndima("Réussite"); else if(a == 6) bwaka("Pas vraiment ça"); bwaka(new Error("erreur")); }); } asyncFunc(5) .then(r => console.log(r)) .catch(erreur => console.log(erreur)) .finally(console.log("Finally")); </script> Avce asyncFunc(5) Avce asyncFunc(6) Promise-Promesse & async-await -40/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Avce asyncFunc(autre) Donc : La définition (ou construction) d’une Promise définit en paramètre la fonction asynchrone [à exécuter au moment de son appel] qui est un CALLBACK. Cette fonction callback qui peut être asynchrone (dans Promise) a au plus, deux paramètres qui sont deux autres fonctions callblack. On fera exécuter le premier paramètre, souvent baptisé « resolve » car il appelle la méthode resolve de l’objet Promise, en cas de réussite (=la promesse a réussi =resolve) pour passer un argument à la méthode « then ». On fera exécuter le deuxième paramètre, souvent baptisé « reject » (appelle la méthode reject de l’objet Promise), en cas d'échec (=la promesse a échoué =reject) aussi pour passer son argument à la méthode « then » le callback à la promise. Le paramètre (fonction callback) de la fonction Promise que vous aurez retenu passera donc son argument à la méthode « then » (de la fonction Promise) dans l'appel. N.B. : 1. Les paramètres et les méthodes ne partagent pas le même « name space », donc il n’y a pas d’interférences possibles entre les noms des paramètres et les noms des méthodes resolve et reject quand ils se retrouvent au niveau des paramètres. 2. Un callback est une fonction de rappel passée en paramètre d’une autre fonction et qui sera appelée ou exécutée le plus souvent Promise-Promesse & async-await -41/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII comme dernière instruction de la dernière fonction qui la reçoit en paramlètre. La méthode « then » peut donc prendre tout au plus un des deux arguments facultatifs (qui sont des CALLBACKs aussi), le premier exécutant s’il y a eu Réussite (selon l’argument du premier paramètre de Promise), et le deuxième argument de « then » s’il y a eu Échec (selon l’argument du deuxième paramètre de Promise). La méthode « then » se comporte elle-même aussi comme une Promise et passe une Promise comme valeur de retour à une éventuelle deuxième « .then » ou une « .catch » via la directive « return » de la fonction qu’elle exécute. Le pseudo-code générique d’une Promise est : var promise = new Promise( function(resolve, reject) { // Tache pouvant bien être async if (/* Quand absolument TOUT a bien marché */) { resolve("msg succès"); } else { // Une ou plusieurs autres choses ont crashé reject(Error("votre msg Échec")); // ou reject(new Error("votre msg Échec")); // L’objet « Error » facilite le débogage // en gardant les traces du stack. } } ); « resolve » et « reject » peuvent être soient des pointeurs sur fonction (comme ci-dessus) ou des fonctions [développées] inline = in situ. Promise-Promesse & async-await -42/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Une autre syntaxe : <input id="inam" onchange="fgo()"> <script type="text/javascript"> "use strict"; let fgo = _ => { const arr = [543,869,1463,2168,1734,1664,598,425,932,1476], r = document.getElementById('inam').value; let sup = arr.filter(element => element > r); console.log("Pour r = ",r); // // // // var promise = new Promise(function(resolve, reject){ if(sup.length) resolve("YES! "+sup+" > "+r) else reject(new Error( "NO! Tous ["+arr+"] inf à "+r ) ) }) . // Notez le point devant then then( function(resolveParam) { console.dir("OK=SUCCESS=FULFILLED!", resolveParam); } , Notez la VIRGULE qui sépare les deux paramètres fonctions callback (ci-dessus & ci-dessous). Celle de dessus c'est pour la réussite (resolve), celle de dessous = pour le fail/erreur (reject), function(rejectParam) { console.dir("KO=FAIL=REJECTED!", rejectParam); } ) console.log(promise); console.log("la suite"); } </script> Promise-Promesse & async-await -43/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Exécution : Notez que l’exécution n’est pas exactement la même dans les deux browsers, et que Promise a exécuté après les instructions qui viennent après elle. Avec FireFox Quantum 62.0.2 : Pour r = 1000 test.html:9:3 Promise { <state>: "pending" } test.html:32:3 Promise { "pending" } <state>: "pending" <prototype>: PromiseProto { … } la suite test.html:33:3 OK=SUCCESS=FULFILLED! YES! 1463,2168,1734,1664,1476 > 1000 test.html:19:7 Pour r = 10000 test.html:9:3 Promise { <state>: "pending" } test.html:32:3 la suite test.html:33:3 KO=FAIL=REJECTED! Error: "NO! Tous [543,869,1463,2168,1734,1664,598,425,932,1476] inf à 10000" test.html:28:7 promise fgo onchange file:///K:/DADET/PROGS/test.html:13:17 file:///K:/DADET/PROGS/test.html:11:17 file:///K:/DADET/PROGS/test.html:1:1 Promise-Promesse & async-await -44/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu Pour r = 100 JavaScript Tome-XXIII test.html:9:3 Promise { <state>: "pending" } test.html:32:3 la suite test.html:33:3 OK=SUCCESS=FULFILLED! YES! 543,869,1463,2168,1734,1664,598,425,932,1476 > 100 test.html:19:7 Avec Yandex 2018 Version 18.10.1.385 beta : test.html:9 Pour r = 1000 test.html:32 Promise {<pending>} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: undefined test.html:33 la suite test.html:19 OK=SUCCESS=FULFILLED! test.html:9 Pour r = 10000 test.html:32 Promise {<pending>} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: undefined test.html:33 la suite test.html:28 KO=FAIL=REJECTED! Comme on l’a dit plus haut, au lieu d’utiliser l’expression var promise = new Promise(function(resolve, reject){…}) Promise-Promesse & async-await -45/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu .then(fresolve,freject) JavaScript Tome-XXIII on peut faire var promise = new Promise(function(resolve, reject){…}) .then(fresolve).then(undefined,freject) Voyons-ça : <script type="text/javascript"> "use strict"; let arr = [1,2,3], p=2; var promise = new Promise(function(resolve, reject){ if(arr.includes(p)) resolve("YES! "+p+" in "+arr) else reject( new Error("NO! "+p+" not.in "+arr) ) }) . // Notez le point devant then then( function(resolveParam) { console.dir("OK=SUCCESS=FULFILLED!", resolveParam); } ) . // Notez le POINT qui sépare les deux then // (ci-dessus & ci-dessous). // Celle de dessus reçoit son argument de resolve // de la Promise, // celle du dessous du then ci-dessus. // // // // then( undefined , function(rejectParam) { console.dir("KO=FAIL=REJECTED!", rejectParam); } ) ou then(undefined,function(rejectParam) { console.dir("KO=FAIL=REJECTED!", rejectParam); } Promise-Promesse & async-await -46/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu // ) JavaScript Tome-XXIII console.log(promise); console.log("la suite"); </script> N.B. : Attention, danger : Il y a des rares situations où les deux callBacks peuvent s’exécuter quel que soit l’état de la Promise (fulfilled ou rejected). Exécution avec Firefox : Promise { <state>: "pending" } test.html:34:1 Promise { "pending" } <state>: "pending" <prototype>: PromiseProto { … } la suite test.html:35:1 OK=SUCCESS=FULFILLED! YES! 2 in 1,2,3 test.html:11:7 Au lieu d’utiliser le deuxième paramètre de « then » (séparé du précédent par une virgule) comme fonction de non succès (ou fonction d’erreur), on peut se servir de « catch » après le « then », et précédé d’un point au lieu de la virgule. Dans ce cas le premier et l’unique paramètre de then (une fonction callback) doit être enfermé dans une paire de parenthèses règlementaires : var promise = new Promise(resolve, reject) . // Notez le point ci-dessus devant then then( function(resolveParam) { console.dir("OK!", resolveParam); } ) Promise-Promesse & async-await -47/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII . // Notez le point ci-dessus devant catch // qui reçoit son argument de // reject de la Promise. catch( function(rejectParam) { console.dir("KO!", rejectParam); } ) Notez que catch a un seul argument, le callback, comme ceci : .catc(function(erreur) {…}). « erreur » est ici la valeur retournée par la Promise, l’argument de « reject ». Illustration : <script type="text/javascript"> "use strict"; let arr = [1,2,3], p=12; var promise = new Promise(function(resolve, reject){ if(arr.includes(p)) resolve("YES! "+p+" in "+arr) else reject(new Error("NO! "+p+" not.in "+arr)) }) . // Notez le point avant then then( function(resolveParam) { console.dir("OK=SUCCESS=FULFILLED!", resolveParam); } ) . // Notez le POINT qui sépare les deux paramètres // fonctions callback (ci-dessus & ci-dessous). // ci-dessus initiée par la méthode « then » // de Promise // si Promise est fulfilled (réussite =resolve), // et ci-dessous initiée par sa méthode « catch ». Promise-Promesse & async-await -48/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII catch(function(rejectParam) { console.dir("KO=FAIL=REJECTED!", rejectParam); } ) // Notez que « .catch » n'a qu'un seul paramètre, // la fonction callback. // Elle n'a pas « undefined » comme premier paramètre. console.log(promise); console.log("la suite"); </script> Exécution avec Firefox : Promise { <state>: "pending" } test.html:29:1 Promise { "pending" } <state>: "pending" <prototype>: PromiseProto { … } catch: function catch() constructor: function Promise() finally: function finally() then: function then() Symbol(Symbol.toStringTag): "Promise" <prototype>: Object { … } la suite test.html:30:1 KO=FAIL=REJECTED! Error: "NO! 12 not.in 1,2,3" promisefile:///K:/DADET/PROGS/test.html:5:17 <anonymous>file:///K:/DADET/PROGS/test.html:3:16 test.html:22:7 Une Promise peut être dans un des 4 états suivants : 1. fulfilled 2. rejected 3. pending - resolved = Réussie Firefox = fulfilled Yandex = resolved - Échec, « failed ». - En cours d’exécution/évaluation Promise-Promesse & async-await -49/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu 4. settled JavaScript Tome-XXIII - Achevée (fulfilled ou rejected). Une promise résolue comporte deux attributs : 1. « state » : indique l’état de la Promise. 2. « value » : donne la valeur de/(retournée par) la Promise. Une promise rejetée comporte deux attributs : 1. « state » : indique l’état de la Promise. 2. « reason » : indique la raison de l’échec. EXEMPLE 4 : resolve inconditionnel. <script> "use strict"; var vpromise = new Promise(function(resolve, reject) { resolve("ARGUMENT DU CALLBACK DE THEN"); // resolve inconditionnel }); console.log(vpromise); vpromise.then(function(Arg_du_CALLBACK_de_then) { console.dir(Arg_du_CALLBACK_de_then); return "Ce then retourne " + Arg_du_CALLBACK_de_then + " au then qui suit"; }) . then(function(retval_du_then_precedent) { console.dir(retval_du_then_precedent); }) </script> Exécution : Promise { <state>: "fulfilled", <value>: "ARGUMENT DU CALLBACK DE THEN" } test.html:7:1 Promise-Promesse & async-await -50/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII ARGUMENT DU CALLBACK DE THEN test.html:10:3 Ce then retourne ARGUMENT DU CALLBACK DE THEN au then qui suit test.html:17:3 EXEMPLE 5 : reject inconditionnel. <script> "use strict"; var vpromise = new Promise(function(resolve, reject) { reject("ARGUMENT DU CALLBACK DE THEN"); // reject inconditionnel }); console.log(vpromise); vpromise . then(function(Arg_du_CALLBACK_de_then) { console.dir(Arg_du_CALLBACK_de_then); return "Ce then retourne " + Arg_du_CALLBACK_de_then + " au then qui suit"; }) . then(function(retval_du_then_precedent) { console.dir(retval_du_then_precedent); }) </script> Exécution avec YANDEX : Promise {<rejected>: "ARGUMENT DU CALLBACK DE THEN"} test.html#:1 Uncaught (in promise) ARGUMENT DU CALLBACK DE THEN test.html:7 1. Promise {<rejected>: "ARGUMENT DU CALLBACK DE THEN"} 1. __proto__: Promise Promise-Promesse & async-await -51/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII 2. [[PromiseStatus]]: "rejected" 3. [[PromiseValue]]: "ARGUMENT DU CALLBACK DE THEN" Exécution avec Firefox : Promise { <state>: "rejected" } test.html:7:1 Promise { "rejected" } <state>: "rejected" <reason>: "ARGUMENT DU CALLBACK DE THEN" <prototype>: PromiseProto { … } test.html:7:1 On peut forcer une Promise à être résolue ou échoué : EXEMPLE 6 : <script type="text/javascript"> "use strict"; const reussi = Promise.resolve('+++ret_OK+++'); // ci-haut : reussi est une Promise forcée à la réussite. reussi .then(result => pReussite(result)) .catch(erreur => pEchec(erreur)) const echec = Promise.reject('---ret_Erreur---'); // ci-haut : echec est une Promise forcée à l'échec. echec .then(result => pReussite(result)) .catch(erreur => pEchec(erreur)) const pReussite = p => console.log(`Promesse OK a retourné/passé : ${p}`); Promise-Promesse & async-await -52/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII const pEchec = p => console.log(`Promesse KO a retourné/passé : ${p}`); // Notez que le code a été gardé exactement le même pour // la suite de la Promise réussie et la Promise échouée. // resolve, reject, then et catch sont des // MÉTHODES de l'objet Promise. </script> Exécution : 17:53:17.960 test.html:20 Promesse OK a retourné/passé : +++ret_OK+++ 17:53:17.964 test.html:23 Promesse KO a retourné/passé : ---ret_Erreur--- EXEMPLE 7 : Forme avec resolve et reject dans la Promise mais sans la deuxième fonction callback (reject) de then : <script> "use strict"; let ar=[1,2,3]; var p=2; var vpromise = new Promise(function(resolve, reject) { if(ar.includes(p))resolve(ar+" contains "+p); else reject(new Error(p+" not in "+ar)) }); console.log(vpromise); vpromise . then(function(Arg_du_CALLBACK_de_then) { console.dir(Arg_du_CALLBACK_de_then); return "Ce then retourne « " + Arg_du_CALLBACK_de_then + Promise-Promesse & async-await -53/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII " » au then suivant"; }) . then(function(retval_du_then_precedent) { console.dir(retval_du_then_precedent); }) </script> Exécution avec fulfilled : [1,2,3].includes(2) Promise { <state>: "fulfilled", <value>: "1,2,3 contains 2" } test.html:10:1 1,2,3 contains 2 test.html:15:3 Ce then retourne « 1,2,3 contains 2 » au then suivant test.html:22:3 Exécution avec rejected : [1,2,3].includes(5) Dans Firefox : Promise { <state>: "rejected" } test.html:10:1 Promise { "rejected" } <state>: "rejected" <reason>: Error: "5 not in 1,2,3" Vpromise file:///K:/DADET/PROGS/test.html:7:15 <anonymous> file:///K:/DADET/PROGS/test.html:5:16 <prototype>: PromiseProto { … } Dans Yandex : test.html:10 Promise { <rejected>: Error: 5 not in 1,2,3 at file:///K:/DADET/PROGS/test.html:7:15 at new Promise (<anonymous>) Promise-Promesse & async-await -54/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu …} JavaScript Tome-XXIII test.html:7 Uncaught (in promise) Error: 5 not in 1,2,3 test.html:10 Promise { <rejected>: Error: 5 not in 1,2,3 at file:///K:/DADET/PROGS/test.html:7:15 at new Promise (<anonymous>) …} __proto__: Promise [[PromiseStatus]]: "rejected" [[PromiseValue]]: Error: 5 not in 1,2,3 at file:///K:/DADET/PROGS/test.html:7:15 at new Promise (<anonymous>) at file:///K:/DADET/PROGS/test.html:5:16 test.html:7 Uncaught (in promise) Error: 5 not in 1,2,3 EXEMPLE 8 : Forme complète de la Promise, avec resolve et reject ainsi que les deux fonctions callback de then. Les exécutions sont exactement les mêmes pour les deux navigateurs : <script> "use strict"; let ar=[1,2,3]; var p=2; var vpromise = new Promise(function(resolve, reject) { if(ar.includes(p))resolve(ar+" contains "+p); else reject(new Error(p+" not in "+ar)) }); console.log(vpromise); vpromise . // Point then( function(Arg_du_CALLBACK_de_then) { console.dir(Arg_du_CALLBACK_de_then); return "Ce then retourne RESOLVE « " + Arg_du_CALLBACK_de_then + Promise-Promesse & async-await -55/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII " » au then suivant"; } , // virgule entre les deux fonctions callback. function(Arg_du_CALLBACK_de_then) { console.dir(Arg_du_CALLBACK_de_then); return "Ce then retourne REJECT « " + Arg_du_CALLBACK_de_then + " » au then suivant"; }, ) . // Point then(function(retval_du_then_precedent) { console.dir(retval_du_then_precedent); }) </script> Exécution avec fulfilled : Dans Yandex : Promise {<resolved>: "1,2,3 contains 2"} test.html:16 1,2,3 contains 2 test.html:31 Ce then retourne RESOLVE « 1,2,3 contains 2 » au then suivant test.html:10 Promise {<resolved>: "1,2,3 contains 2"} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: "1,2,3 contains 2" test.html:16 1,2,3 contains 2 test.html:31 Ce then retourne RESOLVE « 1,2,3 contains 2 » au then suivant Promise-Promesse & async-await -56/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Dans Firefox : Promise { <state>: "fulfilled", <value>: "1,2,3 contains 2" } test.html:10:1 1,2,3 contains 2 test.html:16:5 Ce then retourne RESOLVE « 1,2,3 contains 2 » au then suivant test.html:31:3 Promise { "fulfilled" } <state>: "fulfilled" <value>: "1,2,3 contains 2" <prototype>: PromiseProto { … } test.html:10:1 1,2,3 contains 2 test.html:16:5 Ce then retourne RESOLVE « 1,2,3 contains 2 » au then suivant test.html:31:3 EXEMPLE 9 : Forme complète de Promise avec pointeurs sur fonctions callback au lieu des fonctions développées inline. Les exécutions sont aussi exactement les mêmes pour les deux navigateurs, mais le code source est plus éloquent. <script> "use strict"; let ar=[1,2,3]; var p=23; Promise-Promesse & async-await -57/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII let freject = (Arg_du_reject) => { console.dir(Arg_du_reject); return "Ce then retourne REJECT « " + Arg_du_reject + " » au then suivant"; } let fretval = function(retval_du_then_precedent) { console.dir(retval_du_then_precedent); } var vpromise = new Promise(function(resolve, reject) { if(ar.includes(p))resolve(ar+" contains "+p); else reject(new Error(p+" not in "+ar)) }); console.log(vpromise); vpromise.then(fresolve , freject).then(fretval) function fresolve(Arg_du_resolve){ console.dir(Arg_du_resolve); return "Ce then retourne RESOLVE « " + Arg_du_resolve + " » au then suivant"; } </script> EXEMPLE 10 : Sans la syntaxe vpromise.then(fresolve , freject) on utilise then pour la réussite et catch pour l’échec, comme ci-après, avec exactement la même exécution : vpromise.then(fresolve).catch(freject) Une succession de « .then » et de « .catch » s’appelle chaîne de « Promises » dans laquelle « l’output » de la fonction qui précède sert de « input » de la fonction qui suit. La fonction précédente devient à son tour une Promise et la valeur qu’elle retourne devient Promise-Promesse & async-await -58/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII l’argument de la fonction suivante introduite par then ou catch. <script> "use strict"; let ar=[1,2,3]; var p=23; let freject = (Arg_du_reject) => { console.dir(Arg_du_reject); return "Ce then retourne REJECT « " + Arg_du_reject + " » au then suivant"; } let fretval = function(retval_du_then_precedent) { console.dir(retval_du_then_precedent); } var vpromise = new Promise(function(resolve, reject) { if(ar.includes(p))resolve(ar+" contains "+p); else reject(new Error(p+" not in "+ar)) }); console.log(vpromise); vpromise.then(fresolve).catch(freject).then(fretval) function fresolve(Arg_du_resolve){ console.dir(Arg_du_resolve); return "Ce then retourne RESOLVE « " + Arg_du_resolve + " » au then suivant"; } </script> Exécution avec fail : Dans Yandex : test.html:21 Promise {<rejected>: Error: 23 not in 1,2,3 at file:///K:/DADET/PROGS/test.html:18:15 at new Promise (<anonymous>…} Promise-Promesse & async-await -59/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII test.html:6 Error: 23 not in 1,2,3 at file:///K:/DADET/PROGS/test.html:18:15 at new Promise (<anonymous>) at file:///K:/DADET/PROGS/test.html:16:16 test.html:13 Ce then retourne REJECT « Error: 23 not in 1,2,3 » au then suivant Dans Firefox : Promise { <state>: "rejected" } <state>: "rejected" <reason>: Error: "23 not in 1,2,3" test.html:21:1 Error: "23 not in 1,2,3" Vpromise file:///K:/DADET/PROGS/test.html:18:15 <anonymous> file:///K:/DADET/PROGS/test.html:16:16 test.html:6:5 Ce then retourne REJECT « Error: 23 not in 1,2,3 » au then suivant test.html:13:3 EXEMPLE 11 : Si la Promise n’est pas résolue, ou que l’une des .then précédent la première .catch défaillit, l’exécution saute au premier .catch en sautant toutes les .then qu’elle rencontrera alors. Un autre exemple de chaîne de Promises : <script type="text/javascript"> "use strict"; let ar=[1,2,3], a=2; let promise = new Promise(function(resolve,reject){ if(ar.includes(a)) resolve("<<< OK 123 >>>"); else reject(">>> FAIL ["+a+" not.in "+ar+"] <<<"); Promise-Promesse & async-await -60/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu }) JavaScript Tome-XXIII promise .then( function(resolve,reject) { let v1 = "v1 = "+resolve; console.log(v1); const ps=" "+v1+" | " // // // // // // Jouez avec les 3 possibilités ci-dessous : return, resolve, reject conjointement avec la valeur de a (ligne 2) soit qu'elle est ou pas contenue dans ar. return("RETURN"+ps); resolve("RESOLVE"+ps); reject("REJECT"+ps); } ) .then(function(resolve,reject) { let v2 = new Error("v2 = "+resolve+" § "); console.log(v2); return(v2); } ) .catch(function(reject) { let v3 = new Error("v3 = "+reject+" $ "); console.log(v3); return(v3); } ) .then(function(resolve,reject) { let v4 = "** v4 ** "+resolve+" £ "; console.log(v4); return "RESOLVE v4 = "+v4; } ) .catch(function(reject) { let v5 = "### "+new Error("v5 = "+reject) + " ###"; console.log(v5); return v5; } ) Promise-Promesse & async-await -61/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu console.log(promise) JavaScript Tome-XXIII </script> Une des exécutions, avec a=2 donc appartenant à [1,2,3] Promise { <state>: "fulfilled", <value>: "<<< OK 123 >>>" } <state>: "fulfilled" <value>: "<<< OK 123 >>>" <prototype>: PromiseProto { … } test.html:51:1 v1 = <<< OK 123 >>> test.html:13:8 Error: "v2 = RETURN v1 = <<< OK 123 >>> | § " <anonymous> file:///K:/DADET/PROGS/test.html:27:17 test.html:28:8 ** v4 ** Error: v2 = RETURN v1 = <<< OK 123 >>> | test.html:40:8 § £ Une autre exécution, avec a=12 (n’appartenant pas à [1,2,3]) Promise { <state>: "rejected" } <state>: "rejected" <reason>: ">>> FAIL [12 not.in 1,2,3] <<<" <prototype>: PromiseProto { … } test.html:51:1 Error: "v3 = >>> FAIL [12 not.in 1,2,3] <<< $ " <anonymous> file:///K:/DADET/PROGS/test.html:33:17 test.html:34:8 ** v4 ** Error: v3 = >>> FAIL [12 not.in 1,2,3] <<< $ test.html:40:8 EXEMPLE 12 : Promise-Promesse & async-await -62/97- jeudi, 4. avril 2019 (10:43 ) £ J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII <script type="text/javascript"> "use strict"; // Définition de la fonction Promise "fpromise" // "ppromise" = adresse fonction à exécuter par fpromise const fpromise = new Promise(ppromise); // Les deux Paramètres de fpromise ou ppromise : // fonction "siResolue" = si succès // fonction "siEchec" = si pas résolue var d, x function ppromise(siResolue, siEchec) { d=new Date(); x=siResolue // "x" = alias de "siResolue" setTimeout(fsettimeout, 3000); } // La fonction de setTimeout. // Prend l'adresse de siResolue à la ligne 15. function fsettimeout(){ x('"Promise1" résolue après '+(new Date()-d)+' ms.') } // // // // // // // // // // // // // // // // Etape finale. A la ligne 45, La fonction "disp" qui fait suite à "fpromise" via l'argument de la méthode "then" de Promise, au point d'entrée, et appelée à la ligne 51, reçoit la valeur de son argument disp du paramètre "siResolue" de la fonction "ppromise" (stockée en alias dans la variable-fonction x à la ligne 15 qui prend son argument à la ligne 24, et déclarée comme variable globale à la ligne 12), la fonction "ppromise" étant appelée par la fonction fpromise (la promesse). siResolue et siEchec (ici dans "x") représentent l'une des valeurs [retournées par] la Promise. Promise-Promesse & async-await -63/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu function disp(t){ console.dir(t) console.dir(fpromise) } JavaScript Tome-XXIII // Point d'entrée. fpromise.then(disp) // "Promise" résolue après 3000 ms (entre 3000 et 3017). console.dir("Waiting1 ...") console.dir(fpromise) </script> EXEMPLE 13 : Vérifier si un élément est membre d’une array : <script type="text/javascript"> "use strict"; const a = new Array(1,2,3); function testArray(p) { // Cette fonction retourne une Promise // Les deux paramètres de notre Promise sont // baptisés ici «resolve» et «reject». return new Promise(function(resolve, reject) { if(a.includes(p))(function() { resolve(p+" dans "+a); })(); // Une Promise résolue est en état "fulfilled" else (function() { reject(new Error(p+' pas dans ' +a)); })(); // Une Promise rejetée est en état "rejected" }); // Indifféremment la Promise est en état "settled". } let r = testArray(23); Promise-Promesse & async-await -64/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu console.log(r); </script> JavaScript Tome-XXIII Exécution : A. Avec let r=testArray(5) "23" n'est pas membre de l'array a, donc la promise est rejetée. Avec YANDEX Version 18.10.1.385 beta Message d'erreur : test.html:16 Uncaught (in promise) Error: 23 pas dans 1,2,3 Affichage : test.html:24 Promise {<rejected>: Error: 23 pas dans 1,2,3 __proto__: Promise [[PromiseStatus]]: "rejected" [[PromiseValue]]: Error: 23 pas dans 1,2,3 Avec FIREFOX Quantum Version 60.0.1 Message d'erreur : Error: 23 pas dans 1,2,3 test.html:16:15 Affichage : Promise { <state>: "rejected" } test.html:24:2 Promise { "rejected" } <state>: "rejected" Promise-Promesse & async-await -65/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII <reason>: Error: 23 pas dans 1,2,3 Stack trace:… B. Avec let r=testArray(2) "2" est membre de l'array a, donc la promise est resolue. Avec YANDEX Version 18.10.1.385 beta PAs de Messages d'erreur : Affichage : Promise {<resolved>: "2 dans 1,2,3"} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: "2 dans 1,2,3" Avec FIREFOX Quantum Version 60.0.1 Pas de Messages d'erreur : Affichage : Promise { <state>: "fulfilled", <value>: "2 dans 1,2,3" } <state>: "fulfilled" <value>: "2 dans 1,2,3" __proto__: PromiseProto { … } test.html:20:1 EXEMPLE 14 : Exemple type où on doit prendre une décision en fonction du résultat d’une action dont on doit attendre le parachèvement : le chargement Promise-Promesse & async-await -66/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII complet d’une page web, d’une image, d’un fichier disque… <script type="text/javascript"> "use strict"; var img; function loadImg(url) { // Cette fonction retourne une Promise return new Promise(function(resolve, reject) { img = new Image(); img.src = url; img.onload = function() { resolve(img); // Paramètre img renvoyé si le chargement a // réussi "fulfilled". // Change l’état de la Promise en « resolved » }; img.onerror = function() { reject(new Error('Could not load image at ' + url)); // Etat de l'erreur renvoyé si le chargement // a échoué "rejected" // Change l’état de la Promise en « rejected » }; }); } const r=loadImg("http://fai.dom"); console.log(r) console.log("la suite") </script> Exécution : Notez que la dernière instruction dans ce code console.log("la suite") Exécute avant la fin de la Promise (les opérations sur l’URL de l’image). Avec Yandex: test.html:25 Promise-Promesse & async-await -67/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu Promise {<pending>} JavaScript Tome-XXIII test.html:26 la suite fai.ext/:1 GET http://fai.dom/ net::ERR_INTERNET_DISCONNECTED Image (async) (anonymous) @ test.html:6 loadImg @ test.html:4 (anonymous) @ test.html:24 test.html:16 Uncaught (in promise) Error: Could not http://fai.dom at Image.img.onerror (test.html:16) img.onerror error (async) (anonymous) loadImg (anonymous) load image at @ test.html:16 @ test.html:15 @ test.html:4 @ test.html:24 Avec Firefox: Promise { <state>: "pending" } test.html:25:1 la suite test.html:26:1 Error: Could not load image at http://fai.dom test.html:16:14 EXEMPLE 15 : Une façon, compacte d'écrire une Promise : <script type="text/javascript"> "use strict"; const fpromisec = new Promise ( function(ifResolved, ifFail ) { const d=new Date(); Promise-Promesse & async-await -68/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII setTimeout ( function () { ifResolved('"Promise2" résolved after ' + (new Date()-d)+' ms.') } , 3000 ); }); // Point d'entrée fpromisec.then(function(t){ console.dir(t) console.dir(fpromisec) }) // "Promise" résolue après 3000 ms. console.dir("Waiting2 ...") console.dir(fpromisec) </script> AFFICHAGE DE LA VERSION COMPACTE : AVEC YANDEX VERSION 18.9.1.464 BETA : test.html:50 Waiting1 ... test.html:51 Promise {<pending>} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: ""Promise1" résolue après 3003 ms." test.html:74 Waiting2 ... test.html:75 Promise {<pending>} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: ""Promise2" résolved after 3009 ms." test.html:41 test.html:69 "Promise1" résolue après 3003 ms. "Promise2" résolved after 3009 ms. ++++++++++==========++++++++++ AVEC FIRFOX QUANTUM 62.0.2 : Waiting1 ... test.html:51:1 Promise-Promesse & async-await -69/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu Promise { <state>: "pending" } Waiting2 ... Promise { "pending" } <state>: "pending" <prototype>: PromiseProto { … } JavaScript Tome-XXIII test.html:52:1 test.html:76:1 test.html:77:1 "Promise1" résolue après 3002 ms. test.html:41:7 Promise { <state>: "fulfilled", <value>: "\"Promise1\" résolue après 3002 ms." } test.html:42:4 "Promise2" résolved after 3012 ms. test.html:70:7 Promise { "fulfilled" } <state>: "fulfilled" <value>: "\"Promise2\" résolved after 3012 ms." <prototype>: PromiseProto catch: function catch() constructor: function Promise() finally: function finally() then: function then() Symbol(Symbol.toStringTag): "Promise" <prototype>: Object { … } <prototype>: {…} __defineGetter__: function __defineGetter__() __defineSetter__: function __defineSetter__() __lookupGetter__: function __lookupGetter__() __lookupSetter__: function __lookupSetter__() constructor: function Object() hasOwnProperty: function hasOwnProperty() isPrototypeOf: function isPrototypeOf() propertyIsEnumerable: function propertyIsEnumerable() toLocaleString: function toLocaleString() toSource: function toSource() toString: function toString() valueOf: function valueOf() Promise . all : Il peut se faire qu’on ait à tester en une seule opération plusieurs Promises (processus) avec une array de Promises. L’array résultant de cette array de Promises servira comme paramètre du CALLBACK des « then » qui suivent. Promise-Promesse & async-await -70/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII EXEMPLE 16 : Tous, des « resolves ». Fonctions asynchrones définies en tant que fonctions fléchées : <script> "use strict"; let p1 = new Promise(function(rs,rj){ rs ("p1 résolu") }), p2 = new Promise(function(rs,rj){ rs ("p2 résolu") }), p3 = new Promise(function(rs,rj){ rs ("p3 résolu") }); Promise.all([p1,p2,p3]) .then(function(arrayDesResultats) { console.dir(arrayDesResultats); var rP1 = arrayDesResultats[0]; var rP2 = arrayDesResultats[1]; var rP3 = arrayDesResultats[2]; console.log(rP1,rP2,rP3); }) . catch(err => { // Premier rejet de toutes les Promises console.log(err) }) . finally(console.log("Finally")); </script> Exécution : Promise-Promesse & async-await -71/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Fonctions asynchrones définies en tant que fonctions ordinaires : <script type="text/javascript"> "use strict"; function asyncFunc1(){ return new Promise((rs,rj) => rs("Succes_1")); } function asyncFunc2(){ return new Promise((rs,rj) => rs("Sucess_2")); } function asyncFunc3(){ return new Promise((rs,rj) => rs("Sucess_3")); } Promise.all( [asyncFunc1(),asyncFunc2(),asyncFunc3()] ) .then(r => { console.log(r); for(let k of r) console.log(k) }) .catch(err => { // Premier rejet de toutes les Promises console.log(err) }) .finally(console.log("Finally")); </script> Promise-Promesse & async-await -72/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII EXEMPLE 17 : Avec au moins un « reject ». Le test s’arrête dès que le premier « reject » est rencontré. <script type="text/javascript"> "use strict"; function asyncFunc1(){ return new Promise((rs,rj) => rs("Succes_1")); } function asyncFunc2(){ return new Promise((rs,rj) => rj("Rejet_2")); } function asyncFunc3(){ return new Promise((rs,rj) => rj("Rejet_3")); } Promise.all( [asyncFunc1(),asyncFunc2(),asyncFunc3()] ) .then(arrayDesResultats => { console.log(arrayDesResultats); for(let k of arrayDesResultats) console.log(k) }) .catch(function(erreur){ console.dir(erreur) console.dir(erreur.status) console.dir(new Error(erreur)) console.dir(new Error(erreur.status)) }) .finally(console.log("Finally")); </script> Exécution avec Yandex : Promise-Promesse & async-await -73/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII En comparaison et pour rappel, voici la syntaxe du « try…catch…finally » : <SCRIPT> "use strict"; try { doAnyWrongThing("?"); } catch (err) { throw "Here in catch"; } finally { console.log("FINALLY!"); } </SCRIPT> ENVOI D’ARGUMENTS À UNE PROMISE : Pour envoyer des arguments à une Promise, il suffit de l’incorporer dans une fonction que l’on peut appeler avec ces arguments. Pour explorer cette promise en dehors de la fonction, cette fonction doit retourner la Promise. EXEMPLE 18 : Promise-Promesse & async-await -74/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII .then avec les deux paramètres fonctions callback : <script type="text/javascript"> "use strict"; function testArray(p) { // Cette fonction retourne une Promise // Les deux paramètres de notre Promise sont // baptisés ici «resolve» et «reject». return new Promise(function(resolve, reject) { var a = new Array(1,2,3); if(a.includes(p))(function() { resolve(p+" dans "+a); })(); // Une Promise résolue est en état "fulfilled" else (function() { reject(new Error(p+' pas dans ' +a)); })(); // Une Promise rejetée est en état "rejected" }); // Indifféremment la Promise est en état "settled". } let r = testArray(12); console.log(r); </script> Exécution avec Firefox : Promise { <state>: "rejected" } test.html:24:2 Promise { "rejected" } <state>: "rejected" <reason>: Error: "12 pas dans 1,2,3" testArray file:///K:/DADET/PROGS/test.html:16:15 testArray file:///K:/DADET/PROGS/test.html:15:12 testArray file:///K:/DADET/PROGS/test.html:7:11 <anonymous> file:///K:/DADET/PROGS/test.html:23:10 <prototype>: PromiseProto catch: function catch() constructor: function Promise() finally: function finally() then: function then() Promise-Promesse & async-await -75/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Symbol(Symbol.toStringTag): "Promise" <prototype>: Object { … } Error: 12 pas dans 1,2,3 test.html:16:15 Exécution avec Yandex : test.html:24 Promise {<rejected>: Error: 12 pas dans 1,2,3 at file:///K:/DADET/PROGS/test.html:16:15 at file:///K:/DADET/PROGS…} test.html:16 Uncaught (in promise) Error: 12 pas dans 1,2,3 at test.html:16 at test.html:17 at new Promise (<anonymous>) at testArray (test.html:7) at test.html:23 test.html:24 Promise {<rejected>: Error: 12 pas dans 1,2,3 at file:///K:/DADET/PROGS/test.html:16:15 at file:///K:/DADET/PROGS…} __proto__: Promise [[PromiseStatus]]: "rejected" [[PromiseValue]]: Error: 12 pas dans 1,2,3 at file:///K:/DADET/PROGS/test.html:16:15 at file:///K:/DADET/PROGS/test.html:17:8 at new Promise (<anonymous>) at testArray (file:///K:/DADET/PROGS/test.html:7:11) at file:///K:/DADET/PROGS/test.html:23:10 test.html:16 Uncaught (in promise) Error: 12 pas dans 1,2,3 at test.html:16 at test.html:17 at new Promise (<anonymous>) at testArray (test.html:7) at test.html:23 (anonymous) @ test.html:16 (anonymous) @ test.html:17 testArray @ test.html:7 Promise-Promesse & async-await -76/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu (anonymous) @ test.html:23 JavaScript Tome-XXIII PROMISE . RACE ( ) : Fonctionne à peu près comme « promise.all », mais elle teste seulement si la première Promise dans la liste de race est résolue ou pas. Si elle est résolue, elle passe sa valeur à la méthode .then, si non, elle passe la « reason » de l’erreur à la méthode .catch. EXEMPLE 19 : <script> "use strict"; let p1 = new Promise(function(resolve,reject){ resolve('"p1 résolu"') }), p2 = new Promise(function(resolve,reject){ reject('"p2 rejeté"') }); Promise.race([p1,p2]) .then(function(ok) { console.dir(ok) }) . catch(function(erreur){ console.dir(new Error(erreur)) }) </script> Exécution : Avec Promise.race([p1,p2]) on a : Promise-Promesse & async-await -77/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu "p1 résolu" JavaScript Tome-XXIII test.html:12:3 Avec Promise.race([p2,p1]) on a : test.html:16:3 Error: "p2 rejeté" at file:///K:/DADET/PROGS/test.html:16:15 Promises dans une Promise : EXEMPLE 20 : <script type="text/javascript"> "use strict"; const p1 = Promise.resolve([1,2,3].includes(3)); p1.then( result => { console.log( "LES DEUX PROMISES [ALL] DANS LE 1e THEN") console.log(result); const p2 = Promise.resolve([2,4,6].includes(2)); const p3 = Promise.resolve([3,6,9].includes(6)); return Promise.all([p2,p3]); } ).then( retArr =>{ console.log(retArr[0]); console.log(retArr[1]); } ) </script> <script type="text/javascript"> "use strict"; Promise-Promesse & async-await -78/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu console.log("***"); JavaScript Tome-XXIII const p11 = Promise.resolve([1,2,3].includes(3)); p11.then( result => { console.log(result); console.log("***"); return p11; } ).then( retVal => { console.log( "LES DEUX PROMISES [ALL] DANS LE 2e THEN") console.log(retVal); const p21 = Promise.resolve( [5,10,15].includes(5) ); const p31 = Promise.resolve( [10,20,50].includes(20) ); Promise.all([p21,p31]).then( retArr => { console.log(retArr[0]); console.log(retArr[1]); } ) } ) </script> Exécution : 22:32:30,076 LES DEUX PROMISES [ALL] DANS LE 1e THEN test.html:7:8 22:32:30,078 22:32:30,079 22:32:30,079 true true true test.html:9:9 test.html:16:9 test.html:17:9 Promise-Promesse & async-await -79/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu 22:32:30,080 22:32:30,081 22:32:30,082 *** true *** JavaScript Tome-XXIII test.html:26:1 test.html:32:9 test.html:33:9 22:32:30,082 LES DEUX PROMISES [ALL] DANS LE 2e THEN test.html:38:13 22:32:30,083 22:32:30,083 22:32:30,084 true true true test.html:40:13 test.html:52:18 test.html:53:18 LES PROPRIÉTÉS DE L’OBJET PROMISE ET DE SON PROTOTYPE : Promise() all: function all() length: 1 name: "Promise" prototype: PromiseProto { … } catch: function catch() constructor: function Promise() finally: function finally() then: function then() Symbol(Symbol.toStringTag): "Promise" <prototype>: Object { … } race: function race() reject: function reject() resolve: function resolve() Symbol(Symbol.species): Getter <prototype>: () apply: function apply() arguments: null bind: function bind() call: function call() caller: null constructor: function Function() length: 0 Promise-Promesse & async-await -80/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII name: "" toSource: function toSource() toString: function toString() Symbol(Symbol.hasInstance): function Symbol.hasInstance() <prototype>: Object { … } LES ATTRIBUTS DES PROPRIÉTÉS DE L’OBJET « PROMISE » : Surtout l’attribut « writable ». Object.getOwnPropertyDescriptors(Promise) 1. {length: {…}, name: {…}, prototype: {…}, all: {…}, race: {…}, …} 1. all: {value: ƒ, writable: true, enumerable: false, configurable: true} 2. length: {value: 1, writable: false, enumerable: false, configurable: true} 3. name: {value: "Promise", writable: false, enumerable: false, configurable: true} 4. prototype: {value: Promise, writable: false, enumerable: false, configurable: false} 5. race: {value: ƒ, writable: true, enumerable: false, configurable: true} 6. reject: {value: ƒ, writable: true, enumerable: false, configurable: true} 7. resolve: {value: ƒ, writable: true, enumerable: false, configurable: true} 8. Symbol(Symbol.species): {get: ƒ, set: undefined, enumerable: false, configurable: true} 9. __proto__: Object Promise-Promesse & async-await -81/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII II. RÉSUMÉ ASYNC/AWAIT : « async » et « await () » sont deux opérateurs qui, comme leurs noms l’indiquent, permettent aussi des opérations asynchrones et même facilitent la coordination des Promises. « await () » bloque le « processus/fonction async » (et seulement lui pas tout l’ordinateur ou les autres « threads ») jusqu’à sa terminaison, c’est-à-dire que TOUT ce qui vient après « await () » dans cette fonction async DOIT attendre l’accomplissement/parachèvement du processus précédé juste de l’opérateur « await () ». Voici l’ordre du déroulement (flow) de l’exécution d’un programme dans un exemple d’asynchronisation : Sans le « async » et sans « await () » : <script type="text/javascript"> "use strict"; let array = [1,2,3]; /*async*/ function goAsync(array) { console.log("Ds Async avant await"); let t=""; for /*await*/ (let i of array) t += i + " | "; console.log(t, "Ds Async après await"); } goAsync(array); console.log("suite"); </script> Avec « async » et « await () » : Promise-Promesse & async-await -82/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII <script type="text/javascript"> "use strict"; let array = [1,2,3]; async function goAsync(array) { console.log("Ds Async avant await"); let t=""; for await (let i of array) t += i + " | "; console.log(t, "Ds Async après await"); } goAsync(array); console.log("suite"); </script> Voici un exemple avec trois processus « await _enés » dans une même fonction « async ». Notez comment le déroulement du programme suit un cheminement à faire perdre la tête ! Il faut donc beaucoup de vigilance quand on programme des « async », « await », « setTimeout », « setIntervalout », « Promise »… pour garder/prévoir la cohérence de l’exécution du programme. <script type="text/javascript"> "use strict"; let array = [1,2,3]; async function goAsync(array) { var t=""; console.log("(2) Ds Async avant les await"); await ( // (function(){ // console.log("Ds Async 1er await, " + // "AVANT setTimeout"); setTimeout( function() { console.log("(10) Ds Async & " + "setTimeout 1er await AVANT for"); Promise-Promesse & async-await -83/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII for (let i of array) console.log(i); console.log("(11) Ds Async & " + "setTimeout 1er await APRÈS for"); } , 5000 ) // console.log("Ds Async et 1er await," + // " après setTimeout"); ) console.log("(4) Ds Async Ier entre deux await"); // var t=""; await ( (function(){ console.log("(5) Ds Async, 2e await " + " AVANT for...to"); for (let k=0 ; k< 100000 ; k++); console.log( "(6) Ds Async, 2e await APRÈS for...to"); }()) console.log("Ds Async, 2e await"); ); console.log("(7) Ds Async IIè entre deux await"); var t=""; console.log(t+ "(8) Ds Async avant 3è await & for...of"); for await (let i of array) { t += i + " | "; } console.log("(9) ",t, "Ds Async après 3è await & for...of"); } console.log("(1) Point d'entrée ->"); goAsync(array); console.log("(3) suite"); </script> Promise-Promesse & async-await -84/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Mais « async » et « await » ont beaucoup de limitations et fonctionnent mieux (presque obligatoirement) en collaboration avec Promise.et permettent d’écrire un code plus concis plus lisible et donc plus facile à entretenir. <script type="text/javascript"> "use strict"; function fDelayor(ms) { return new Promise( resolve => { setTimeout(() => { console.log(`In the waited process`); resolve(`resolve from promise`); }, ms); // setTimeout() } // resolve ); // Promise() } // function fDelayor() async function asyncFunc() { const promiseRet = await fDelayor(3000); console.log(`Dans asyncFunction, ${promiseRet}`); } console.log(`Entry Point`); asyncFunc(); console.log(`La suite`); </script> Promise-Promesse & async-await -85/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Toutefois, une fonction async (fonction) et une Promise (objet) sont dans beaucoup de cas deux façons différentes d’implémenter exactement la même tâche (algorithme ou pseudocode). Les deux codes « resolve/reject » ci-dessous sont identiques : EXEMPLE 21 : <script type="text/javascript"> "use strict"; // VERTSION Promise function fPromise(a,e){ return new Promise((resolve, reject) => { if(a.includes(e)) resolve(a+".includes("+e+")"); else reject(a+" .not.includes("+e+")"); }) } // VERTSION asyncF async function fAsync(a,e){ if(a.includes(e)) return a+".includes("+e+")"; else throw a+" .not.includes("+e+")"; } const ar=[1,2,3,4,5] , e=5; fPromise(ar , e) .then(result => console.log(`Le Résultat : ${result}`)) .catch(result => console.log(`Le Résultat : ${result}`)) Promise-Promesse & async-await -86/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII fAsync(ar , e) .then(result => console.log(`Le Résultat : ${result}`)) .catch(result => console.log(`Le Résultat : ${result}`)) </script> Exécution avec « e == 3 » : 22:44:49,794 test.html:24:18 Le Résultat : 1,2,3,4,5.includes(3) 22:44:49,796 test.html:29:18 Le Résultat : 1,2,3,4,5.includes(3) Exécution avec « e==7 » : 23:12:31,141 test.html:25:19 Le Résultat : 1,2,3,4,5 .not.includes(7) 23:12:31,142 test.html:30:19 Le Résultat : 1,2,3,4,5 .not.includes(7) Les deux codes sans reject ci-dessous sont aussi identiques bien que pas corrects, et leur fonctionnement n’est pas le même dans Google Chrome Version 70.0.3538.77 (Build officiel) (64 bits) 2018 que dans Firefox Quantum 62.0.2. EXEMPLE 22 : <script type="text/javascript"> "use strict"; // VERTSION Promise function fPromise(a,e){ return new Promise((resolve, reject) => { if(a.includes(e)) resolve(a+".includes("+e+")"); Promise-Promesse & async-await -87/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII else reject(a+" .not.includes("+e+")"); }) } // VERTSION asyncF async function fAsync(a,e){ if(a.includes(e)) return a+".includes("+e+")"; else throw a+" .not.includes("+e+")"; } const ar=[1,2,3,4,5] , e=7; fPromise(ar , e) .then(result => console.log(`Le Résultat : ${result}`)) fAsync(ar , e) .then(result => console.log(`Le Résultat : ${result}`)) </script> Comme il manque le gestionnaire d’exception catch pour le reject, chaque navigateur traite l’erreur à sa façon : Exécution : AVEC GOOGLE CHROME : 23:27:35.732 test.html:1 Uncaught (in promise) 1,2,3,4,5 .not.includes(7) Promise.then (async) (anonymous) @ test.html:24 23:27:35.735 test.html:1 Uncaught (in promise) 1,2,3,4,5 .not.includes(7) Promise-Promesse & async-await -88/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII FIREFOX n’affche absolument rien. Promise-Promesse & async-await -89/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu III. JavaScript Tome-XXIII LES « CALLBACK » : Pour clarifier les idées sur les fonctions CALLBACK (fonctions de rappel), voici quelques autres exemples de leur utilisation, mais essentiellement avec les Arrays et Typed Arrays. Nous avons ci-après des exemples de fonctions CallBack typiques, qui sont automatiquement rappelées pour chaque élément de la liste qu’elles traitent selon exactement les mêmes critères. 1. La méthode « Array . map ( ) » avec les arrays typées : Elle applique une même action à tous les éléments de l’Array et retourne la valeur de l’opération. <script type="text/javascript"> var ar = new Int32Array([100,8000,999,10000,400000 ]); console.log("Notre array:\n"+ar); console.log(""); let chc = el => el // Fonction CALLBACK par excellence let r; r = ar.map(chc); console.log("Chacun des éléments de notre Array:\n"+r); console.log("On peut manipuler Chacun de ces éléments:\n"+r); r = ar.map(e => Math.log10(e)); console.log("Int de « Math.log10(e) » de chac élém:\n"+r); </script> Promise-Promesse & async-await -90/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu Notre array: 100,8000,999,10000,400000 JavaScript Tome-XXIII test.html:3:3 Chacun des éléments de notre Array: 100,8000,999,10000,400000 On peut manipuler Chacun de ces éléments: 100,8000,999,10000,400000 test.html:15:3 Int de « Math.log10(e) » de chac élém: 2,3,2,4,5 test.html:18:3 2. La méthode « Array . filter ( ) » avec les arrays typées : Elle filtre les éléments de l’Array selon le critère spécifié. <script type="text/javascript"> "use strict"; let r; const ar = new Int32Array([79,81,63,80,90,58,61,62,96,24]); console.log("TypedArray initiale: "+ar); console.log(""); let impaires = (element, index, array) => element%2; let paires = (element, index, array) => !(element%2); r = ar.filter(impaires); console.log("Elements impaires: ", r); r = ar.filter(paires); console.log("Elements paires: ", r); </script> TypedArray initiale: 79,81,63,80,90,58,61,62,96,24 test.html:4:5 Elements impaires: Int32Array(4) [ 79, 81, 63, 61 ] test.html:12:5 Elements paires: Int32Array(6) [ 80, 90, 58, 62, 96, 24 ] Promise-Promesse & async-await -91/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII test.html:15:5 3. La méthode « Array pées : . every ( ) avec les Arrays et Arrays Ty- Elle teste si TOUS les éléments de l’Array remplissent le critère spécifié. <script type="text/javascript"> "use strict"; let r; var ar = new Int32Array([90,57,19,53,75,95,18,15,65,94]); console.log("Notre Array: "+ar); console.log("ar.length =",ar.length); console.log("\nDU TOUT ou RIEN"); let Callback0 = (element, index, array) => element<95; let Callback1 = (element, index, array) => !(element<95); let Callback2 = (element, index, array) => element<15; let Callback3 = (element, index, array) => element<15; let Callback4 = (element, index, array) => element>=15; console.log(""); r = ar.every(Callback0); if(r){ console.log("TOUS les console.log("r.length }else { console.log("Au moins console.log("r.length } éléments sont <95 :",r); =",r.length); un élément « !(<95) » :",r); =",r.length); r = ar.filter(Callback1); if(r.length){ console.log("Eléments >=95 :",r); console.log("r.length =",r.length); }else { Promise-Promesse & async-await -92/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII console.log("Au moins un élément « !(>=95) » :",r); console.log("r.length =",r.length); } console.log(""); r = ar.every(Callback2); if(r){ console.log("TOUS les console.log("r.length }else { console.log("Au moins console.log("r.length } éléments sont <15 :",r); =",r.length); un élément « !(<15) » :",r); =",r.length); r = ar.filter(Callback3); if(r.length){ console.log("Au moins un élément <15 :",r); }else { console.log("Aucun élément <15 :",r); } console.log(""); r = ar.every(Callback4); if(r){ console.log("TOUS les console.log("r.length }else { console.log("Au moins console.log("r.length } r = ar.filter(Callback4); if(r){ console.log("TOUS les console.log("r.length }else { console.log("Au moins console.log("r.length } </script> éléments sont >=15 :",r); =",r.length); un élément « !(>=15) » :",r); =",r.length); éléments >=15 :",r); =",r.length); un élément « !(>=15) » :",r); =",r.length); Promise-Promesse & async-await -93/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII « Array . every ( Callback ) » teste si TOUS les éléments de l'Array ou le Typed Array satisfont à la condition énoncée (un peu dans le même ordre d'idée que « Promise.all ») : Si tous les éléments satisfont à la condition, le boolean « true » est retourné, si au moins un élément ne satisfait pas à la condition, le boolean « false » est retourné. Exécution du code ci-dessus : Notre Array: 90,57,19,53,75,95,18,15,65,94 ar.length = 10 test.html:4:4 test.html:5:4 DU TOUT ou RIEN test.html:7:4 Au moins r.length Eléments r.length un élément « !(<95) » : false = undefined >=95 : Int32Array [ 95 ] = 1 test.html:25:7 test.html:26:7 test.html:31:7 test.html:32:7 Au moins un élément « !(<15) » : false r.length = undefined Aucun élément <15 : Int32Array [] test.html:46:7 test.html:47:7 test.html:54:7 TOUS les éléments sont >=15 : true r.length = undefined test.html:61:7 test.html:62:7 TOUS les éléments >=15 : Int32Array(10) [ 90, 57, 19, 53, 75, 95, 18, 15, 65, 94 ] r.length = 10 test.html:71:7 4. La méthode « Array . forEach ( CallBack ) » : Array . forEach ( CallBack ) applique une action exactement de la même façon à TOUS les éléments de l’Array à l’instar de « Array . map ( CallBack ) » , mais contrairement à ce dernier, « forEach » ne Promise-Promesse & async-await -94/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII retourne absolument rien même quand on l’y force, et donc TOUS et absolument TOUS les traitements doivent impérativement être entièrement parachevés dans le CallBack. <script type="text/javascript"> "use strict"; var ar = new Int32Array([90,57,19,53,75,95,18,15,65,94]); console.log("Notre Array: "+ar); let Callback = (element, index, array) => { console.log(element+" < "+65+" :: ", +element<65); return "Nada"; } console.log(""); let r = ar.forEach(Callback); // ar.forEach() ne retourne absolument rien ! console.log("Les éléments retournés :",r); </script> Notre Array: 90,57,19,53,75,95,18,15,65,94 test.html:3:4 90 < 65 :: false 57 < 65 :: true 19 < 65 :: true 53 < 65 :: true 75 < 65 :: false 95 < 65 :: false 18 < 65 :: true 15 < 65 :: true 65 < 65 :: false 94 < 65 :: false Les éléments retournés : undefined test.html:6:8 test.html:6:8 test.html:6:8 test.html:6:8 test.html:6:8 test.html:6:8 test.html:6:8 test.html:6:8 test.html:6:8 test.html:6:8 test.html:15:4 Promise-Promesse & async-await -95/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII Kinshasa, le 4 avril 2019 (10:43 ). Mots-clés : async, callback, await, throw, Promise, Promise.all, Promise.race, Promise.reject, Promise.resolve, promise.catch, resolve, reject, fulfilled, rejected, pending, settled, tâche, asynchrone, réussite, échec, multithreading, Javascript, curryng, fonction englobante, fonction imbriquée, opération, fonction, ECMASCRIPT. Promise-Promesse & async-await -96/97- jeudi, 4. avril 2019 (10:43 ) J.D.B. DIASOLUKA Nz. Luyalu JavaScript Tome-XXIII DIASOLUKA Nz. Luyalu Docteur en Médecine, Chirurgie & Accouchements (1977), CNOM : 0866 - Spécialiste en ophtalmologie (1980) Études humanités : Scientifique - Mathématiques & Physique. Informaticien-amateur, Programmeur et WebMaster. Chercheur indépendant, autonome et autofinancé, bénévole, sans aucun conflit d’intérêt ou liens d'intérêts ou contrainte promotionnelle avec qui qu’il soit ou quelqu’organisme ou institution / organisation que ce soit, étatique, paraétatique ou privé, industriel ou commercial en relation avec le sujet présenté. +243 - 851278216 - 899508675 - 991239212 - 902263541 - 813572818 [email protected] Promise-Promesse & async-await -97/97- jeudi, 4. avril 2019 (10:43 )