{"id":1646,"date":"2020-08-28T19:31:01","date_gmt":"2020-08-28T17:31:01","guid":{"rendered":"http:\/\/blogperso.union31.fr\/?p=1646"},"modified":"2020-08-29T12:03:26","modified_gmt":"2020-08-29T10:03:26","slug":"node-js-javascript-les-promesses-async-et-await","status":"publish","type":"post","link":"https:\/\/blogperso.union31.fr\/?p=1646","title":{"rendered":"Node.js : Javascript, les promesses, async et await"},"content":{"rendered":"\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Sommaire<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/blogperso.union31.fr\/?p=1646\/#I_Introduction\" >I Introduction<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/blogperso.union31.fr\/?p=1646\/#II_Les_callback\" >II Les callback<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/blogperso.union31.fr\/?p=1646\/#II_Les_promesses\" >II Les promesses<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/blogperso.union31.fr\/?p=1646\/#III_Async_et_await\" >III Async et await<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/blogperso.union31.fr\/?p=1646\/#III1_Async\" >III.1 Async<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/blogperso.union31.fr\/?p=1646\/#III2_Await\" >III.2 Await<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"I_Introduction\"><\/span>I Introduction<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Zoom sur le javascript concernant les promesses. Arriv\u00e9e depuis 2017, cette mani\u00e8re d&rsquo;\u00e9crire du code asynchrone devient de plus en plus utilis\u00e9.<\/p>\n\n\n\n<p><span style=\"text-decoration: underline;\">Quelques liens utiles :<\/span><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Pages web : <ul><li>site mozilla : <ul><li>les promesses : <a href=\"https:\/\/developer.mozilla.org\/fr\/docs\/Web\/JavaScript\/Guide\/Utiliser_les_promesses\">https:\/\/developer.mozilla.org\/fr\/docs\/Web\/JavaScript\/Guide\/Utiliser_les_promesses<\/a><\/li><li>async \/ await : <a rel=\"noreferrer noopener\" href=\"https:\/\/developer.mozilla.org\/fr\/docs\/Web\/JavaScript\/Reference\/Instructions\/async_function\" target=\"_blank\">https:\/\/developer.mozilla.org\/fr\/docs\/Web\/JavaScript\/Reference\/Instructions\/async_function<\/a><\/li><\/ul><\/li><li>async \/ await : <a href=\"https:\/\/blog.engineering.publicissapient.fr\/2017\/11\/14\/asyncawait-une-meilleure-facon-de-faire-de-lasynchronisme-en-javascript\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/blog.engineering.publicissapient.fr\/2017\/11\/14\/asyncawait-une-meilleure-facon-de-faire-de-lasynchronisme-en-javascript\/<\/a><\/li><\/ul><\/li><li>vid\u00e9os : <ul><li>les promesses : <a rel=\"noreferrer noopener\" href=\"https:\/\/www.youtube.com\/watch?v=SSYt7C4sCbw\" target=\"_blank\">https:\/\/www.youtube.com\/watch?v=SSYt7C4sCbw<\/a> (juste les promesses)<\/li><li>la totale : <a rel=\"noreferrer noopener\" href=\"https:\/\/www.grafikart.fr\/tutoriels\/promise-async-await-875\" target=\"_blank\">https:\/\/www.grafikart.fr\/tutoriels\/promise-async-await-875<\/a><\/li><\/ul><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"II_Les_callback\"><\/span>II Les callback<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Pour faire du code asynchrone, il y a les callback.<\/p>\n\n\n\n<p>Exemple :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\/\/ simple fonction utilisant un callback\nfunction affiche_differe(temps_ms,callback) {\n\n\tsetTimeout(()=>{\n\t\tcallback()\n\t},temps_ms)\n\n}\n\n\/\/ Main :\n\naffiche_differe(5000, ()=> {\n\tconsole.log(\"Texte \u00e9crit au bout de 5000ms d'attente\")\n})\nconsole.log(\"Ce texte sera affich\u00e9 avant ...\")<\/code><\/pre>\n\n\n\n<p>La fonction \u00ab\u00a0affiche_differe\u00a0\u00bb affiche un texte au bout de 5000ms via la m\u00e9thode de callback.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"II_Les_promesses\"><\/span>II Les promesses<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Les promesses sont des objets instanci\u00e9s de la classe Promise.  Elle prend en param\u00e8tre une fonction de callback utilisant 2 param\u00e8tres : resolve et reject<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>let ma_promesse = new Promise((resolve,reject)=>{\n\n})<\/code><\/pre>\n\n\n\n<p>Ainsi notre exemple pourra ressembler \u00e0 celui-ci :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>let affiche_differe2 = new Promise((resolve,reject)=>{\n\tlet temps_ms = 5000\n\tsetTimeout(()=>{\n\t\tconsole.log(\"Texte affich\u00e9 apr\u00e8s \" + temps_ms + \" ms\")\n\t},temps_ms)\n})<\/code><\/pre>\n\n\n\n<p>Mais 2 petits probl\u00e8mes \u00e0 r\u00e9soudre :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>avoir r\u00e9cup\u00e9rer le callback<\/li><li>avoir ses propres param\u00e8tres d&rsquo;appel : ici il n&rsquo;y en pas car c&rsquo;est un object promise que l&rsquo;on instancie.<\/li><\/ul>\n\n\n\n<p>Ainsi le nouveau code pour l&rsquo;utilisation du call back : utiliser la m\u00e9thode \u00ab\u00a0then\u00a0\u00bb pour r\u00e9cup\u00e9rer le callback du \u00ab\u00a0resolve\u00a0\u00bb et \u00ab\u00a0catch\u00a0\u00bb pour le callback du \u00ab\u00a0reject\u00a0\u00bb :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>let affiche_differe2 = new Promise((resolve,reject)=>{\n\n\tlet temps_ms = 5000\n\t\n\tif (temps_ms) {\n\t\tsetTimeout(()=>{\n\t\t\tresolve(temps_ms)\n\t\t},temps_ms)\n\t} else {\n\t\treject (\"Erreur : pas de temps d\u00e9fini\")\n\t}\n})\n\n\/\/ Main :\naffiche_differe2.then((temps_ms)=>{\n\tconsole.log(\"Texte affich\u00e9 apr\u00e8s \" + temps_ms + \" ms\")\n}).catch((err)=>{\n\tconsole.log(err)\n})<\/code><\/pre>\n\n\n\n<p>Maintenant il reste \u00e0 d\u00e9finir ses param\u00e8tres (dur\u00e9e 5000ms). La solution est d&rsquo;utiliser une fonction qui retournera une promesse :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nfunction affiche_differe_final(temps_ms) {\n\n\t\/\/ cr\u00e9ation d'une promesse\n\tlet une_promesse =  new Promise((resolve,reject)=>{\n\t\tif (temps_ms) {\n\t\t\tsetTimeout(()=>{\n\t\t\t\tresolve(temps_ms)\n\t\t\t},temps_ms)\n\t\t} else {\n\t\t\treject (\"Erreur : pas de temps d\u00e9fini\")\n\t\t}\n\t})\n        \/\/ renvoi de la promesse\n\treturn une_promesse\n}\n\n\n\/\/ Main :\n\n\/\/ ici affiche_differe_final est une promesse : d\u00e9finition des m\u00e9thodes then et catch\naffiche_differe_final(5000).then((temps_ms)=>{\n\tconsole.log(\"Texte affich\u00e9 apr\u00e8s \" + temps_ms + \" ms\")\n}).catch((err)=>{\n\tconsole.log(err)\n})\n\nconsole.log(\"Ce texte sera affich\u00e9 avant ...\")<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"III_Async_et_await\"><\/span>III Async et await<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"III1_Async\"><\/span>III.1 Async<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>L&rsquo;\u00e9criture de fonctions utilisant les promesses donne un code assez verbeux. Le fait d&rsquo;utiliser Async et await va permettre de l&rsquo;etre moins et de lire code come s&rsquo;il \u00e9tait synchrone&#8230;<\/p>\n\n\n\n<p>Une fonction d\u00e9finie avec le mot clef \u00ab\u00a0Async\u00a0\u00bb renvoie obligatoirement une promesse. Le code ci-dessous permet de comprendre la philosophie :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>async function fonctionAsynchroneOk() {\n \/\/ \u00e9quivaut \u00e0 :\n \/\/ return Promise.resolve('r\u00e9sultat');\n return 'r\u00e9sultat';\n}\nfonctionAsynchroneOk().then(console.log) \/\/ log \"r\u00e9sultat\"\n\nasync function fonctionAsynchroneKo() {\n \/\/ \u00e9quivaut \u00e0 :\n \/\/ return Promise.reject(new Error('erreur'));\n throw new Error('erreur');\n}\nfonctionAsynchroneKo().catch(err => console.log(err.message)) \/\/ log \"erreur\"<\/code><\/pre>\n\n\n\n<p>Donc le mot clef \u00ab\u00a0Async\u00a0\u00bb permet de ne plus d\u00e9clarer une promesse dans la fonction et de ne plus faire r\u00e9f\u00e9rence \u00e0 une m\u00e9thode callback \u00ab\u00a0resolve()\u00a0\u00bb ou \u00ab\u00a0reject()\u00a0\u00bb. En revanche, l&rsquo;utilisation de la fonction \u00e9crite n\u00e9cessite d&rsquo;utiliser les callback \u00ab\u00a0then\u00a0\u00bb et \u00ab\u00a0catch\u00a0\u00bb.<\/p>\n\n\n\n<p>Ce qui, en reprenant les exemples ci-dessus, peut donner le code suivant : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>async function affiche_differe3(texte,temps_ms) {\n\tsetTimeout(()=>{\n\t\tconsole.log(texte)\n\t}, temps_ms)\n}\n\n\naffiche_differe3(\"Texte affich\u00e9 apr\u00e8s \" + 5000 + \"ms\", 5000 )\nconsole.log(\"Ce texte sera affich\u00e9 avant ...\")<\/code><\/pre>\n\n\n\n<p>Attention, l&rsquo;utilisation du setTimeout peut am\u00e8ner de la confusion :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>async function affiche_differe3(texte,temps_ms) {\n\tsetTimeout(()=>{\n\t\tconsole.log(texte)\n\t}, temps_ms)\n}\naffiche_differe3(\"Texte affich\u00e9 apr\u00e8s \" + 5000 + \"ms\", 5000 ).then(()=>{console.log(\"fin\")})\nconsole.log(\"Ce texte sera affich\u00e9 avant ...\")<\/code><\/pre>\n\n\n\n<p>Dans ce cas  il sera affich\u00e9 en premier :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>\u00ab\u00a0Ce texte sera affich\u00e9 avant&#8230;&rsquo; ;<\/li><li>\u00ab\u00a0fin\u00a0\u00bb ;<\/li><li>\u00ab\u00a0Texte affich\u00e9 apr\u00e8s 5000ms\u00a0\u00bb ;<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"III2_Await\"><\/span>III.2 Await<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>C&rsquo;est le point le plus int\u00e9ressant. Tout d&rsquo;abord le  mot clef \u00ab\u00a0await\u00a0\u00bb s&rsquo;utilise <span style=\"text-decoration: underline;\">uniquement<\/span> dans une fonction ayant le mot clef \u00ab\u00a0Async\u00a0\u00bb.<\/p>\n\n\n\n<p>Le mot clef await permet :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li> d&rsquo;attendre la r\u00e9solution d&rsquo;une promesse<\/li><li>de retourner le contenu de \u00ab\u00a0resolve()\u00a0\u00bb du return d&rsquo;une fonction async. (rappel : le return d&rsquo;une fonction async renvoie une promesse)<\/li><\/ul>\n\n\n\n<p>Exemple :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>async function chiffre_alea(nombre) {\n\treturn Math.random() * nombre\n}\n\nasync function affiche_total() {\n\n\tlet chiffre1 = await chiffre_alea(10)\n\tconsole.log (\"chiffre 1 : \" + chiffre1)\n\tlet chiffre2 = await chiffre_alea(10)\n\tconsole.log (\"chiffre 2 : \" + chiffre2)\n\tlet chiffre3 = await chiffre_alea(10)\n\tconsole.log (\"chiffre 3 : \" + chiffre3)\n\n\tlet somme = chiffre1 + chiffre2 + chiffre3\n\tconsole.log (\"La somme est :\" + somme)\n}\n\naffiche_total()<\/code><\/pre>\n\n\n\n<p>Ce qui permet d\u2019ex\u00e9cuter du code asynchrone s\u00e9quentiellement (et d&rsquo;avoir l&rsquo;impression de lire du code synchrone).<\/p>\n\n\n\n<p>Pour la gestion des erreurs, il suffira d&rsquo;encapsuler le code d&rsquo;un try\/catch comme suivant :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>async function chiffre_alea(nombre) {\n\tlet valeur = Math.random() * nombre\n\tif (valeur &lt; 0.5) throw new Error('erreur chiffre_alea : chiffre trop petit !!!');\n\treturn valeur\n}\n\nasync function affiche_total() {\n\ttry {\n\t\tlet chiffre1 = await chiffre_alea(10)\n\t\tconsole.log (\"chiffre 1 : \" + chiffre1)\n\t\tlet chiffre2 = await chiffre_alea(10)\n\t\tconsole.log (\"chiffre 2 : \" + chiffre2)\n\t\tlet chiffre3 = await chiffre_alea(10)\n\t\tconsole.log (\"chiffre 3 : \" + chiffre3)\n\t\tlet somme = chiffre1 + chiffre2 + chiffre3\n\t\tconsole.log (\"La somme est :\" + somme)\n\t} catch (erreur) {\n\t\tconsole.log(erreur)\n\t}\t\n\t\n}\n\naffiche_total()\n<\/code><\/pre>\n\n\n\n<p>ce qui donne le r\u00e9sultat suivant :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chiffre 1 : 5.422324576298465\nchiffre 2 : 7.463496462045109\nchiffre 3 : 8.638824117224802\nLa somme est :21.524645155568376<\/code><\/pre>\n\n\n\n<p>ou celui-ci en cas d&rsquo;erreur :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chiffre 1 : 4.832829568647341\nError: erreur chiffre_alea : chiffre trop petit !!!\n    at chiffre_alea (C:\\nodejs_www\\test7_msql2\\callback.js:30:26)\n    at affiche_total (C:\\nodejs_www\\test7_msql2\\callback.js:40:24)\n    at processTicksAndRejections (internal\/process\/task_queues.js:97:5)<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I Introduction Zoom sur le javascript concernant les promesses. Arriv\u00e9e depuis 2017, cette mani\u00e8re d&rsquo;\u00e9crire du code asynchrone devient de plus en plus utilis\u00e9. Quelques liens utiles : Pages web : site mozilla : les promesses : https:\/\/developer.mozilla.org\/fr\/docs\/Web\/JavaScript\/Guide\/Utiliser_les_promesses async \/<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1646","post","type-post","status-publish","format-standard","hentry","category-non-classe"],"_links":{"self":[{"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=\/wp\/v2\/posts\/1646","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1646"}],"version-history":[{"count":13,"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=\/wp\/v2\/posts\/1646\/revisions"}],"predecessor-version":[{"id":1662,"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=\/wp\/v2\/posts\/1646\/revisions\/1662"}],"wp:attachment":[{"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1646"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogperso.union31.fr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}