Topic outline

  • General

    Bienvenue dans le cours sur la programmation asynchrone en JavaScript. Ce concept est extrêmement utilisé aujourd'hui, il va donc falloir bien le maitriser

    La programmation asynchrone sert principalement à deux choses en Javascript :

    1. faire des animations
    2. récupérer des données sur un serveur distant


    En tant que développeur débutant, vous serez plus concerné par le point n°2 : récupérer des données sur un serveur distant. Réaliser des animations propres (et non bugguées) peut vite se révéler être assez complexe, donc on utilise généralement des librairies spécialisées pour faire cela. Mais ne vous inquiétez pas, on va quand même faire mumuse et faire bouger des trucs ;) Juste pour ce faire la main !


    Nous allons découvrir tout ça maintenant, mais pour cela, il vous faut bien maitriser :

    1. les bases de la programmation en JavaScript
    2. la manipulation du DOM (à part si vous souhaitez rester bloqué dans votre console)
    3. les fonctions anonymes et les callback (très utilisées lorsque l'on code en asynchrone)


    Vous êtes prêt ? Attention au compte à rebours :


    3

    2

    1

    .....

    C'est parti !

    • Présentation

      Le concept de programmation asynchrone permet de différer l'exécution d'une fonction. Ce qui sous entend une notion temporelle, c'est pour cela que l'on parle de programmation asynchrone. Cela veux dire qu'une fonction dite asynchrone sera exécutée forcément au bout d'un certains temps. 

      Contrairement à la programmation dites synchrone, c'est à dire que les choses se font "dans l'ordre", la programmation asynchrone fait rentrer une notion de "temps d'attente" qui est indispensable dans certains cas. 

      Exemples :

      • pour les animations, on va faire bouger un élément de quelques pixels toutes les 40ms, et cela va donner l'illusion du mouvement
      • pour récupérer les données sur un serveur, on va émettre une requête à l'aide de JS, et on attendra une réponse pour mettre à jour notre page.


      Comme vous pouvez le voir dans l'exemple ci-dessus, parfois on connait le temps d'attente (animation), puis parfois, on ne le connait pas (attente d'une réponse du serveur). On pourra gérer facilement les deux cas en JavaScript.

      Le concept d'attente

      Des fois on sait

      js async prog example

      Desfois, on sait pas...


      Un concept important à comprendre lorsque l'on fait de la programmation asynchrone, c'est le fait que votre code est non-bloquant. Cela veux dire que lorsqu'une fonction est en attente d'être déclenchée, cela n'empêche pas le reste du programme de continuer à s'exécuter. On dit alors que le code est non-bloquant. Il ne s'exécute pas dans un ordre connu à l'avance, et l'attente du déclenchement d'une fonction n'empêche pas les autres de continuer à bien fonctionner. Un peu comme en programmation événementielle.


      Conclusion

      Donc aujourd'hui, la programmation asynchrone est présente partout dans le monde du web et du JS, et vous pourrez difficilement vous en passer. La "logique" asynchrone est un peu plus complexe que du code synchrone standard, car nous devons sans arrêt avoir en tête que le code que nous écrivons ne s’exécute pas forcément dans l'ordre dans lequel nous l'écrivons. Cela demande une certaine gymnastique mentale, mais une fois qu'on a compris les grandes lignes, tout cela reste logique. 

      En revanche, la syntaxe qui permet d'écrire du code asynchrone n'est pas toujours adaptée, et dans certains cas, un programme asynchrone peut vite devenir illisible car trop enchevêtré. De nouvelles syntaxes, et de nouveaux mot clés ont fait leur apparitions en Javascript pour permettre une écriture du code plus "propre", mais comme nous l'avons vu dans les cours précédents, il y a toujours un usage "à l'ancienne", un usage "à la pointe", et 50 nuances de JS entre les deux... Nous parlerons de la majorité des méthodes disponibles pendant la théorie, mais en pratique, nous utiliserons les techniques actuelles durant la formation.

      • Timers et animations

        Pour commencer à découvrir la programmation asynchrone, utilisons des fonctions simples de JS : les timers. Comme leurs noms l'indiquent, les timers vont vous permettre de différer l'exécution d'un code ou d'une fonction. 

        Voici les deux timers JS :

        1. setTimeout() : permet d'attendre un certains temps avant d'exécuter une fonction
        2. setInterval() : exécute une fonction suivant un intervalle de temps régulier


        Ces fonctions prennent un callback en premier paramètre, et une durée en milliseconde en deuxième paramètre.



        Mettre en place un compte à rebours : setTimeout()

        Avec setTimeout(), on va découvrir que certaines parties du code peuvent être exécutées de manière différée :

        <meta charset="utf-8">
        <script>
        console.log('Début du script');
        setTimeout(function(){
        console.log('Déclenchement du timer'); /* Ce code ne sera exécuté qu'après 2000ms (2s) */
        },2000)
        console.log('Fin du script');
        </script>

        Dans cet extrait de code, l'ordre d'affichage dans la console sera le suivant :

        1. début du script
        2. fin du script
        3. déclenchement du timer


        Déroutant, mais extrêmement puissant.... Cette notion de temps d'attente est absolument cruciale pour la suite.

        Donc pour conclure, setTimeout() est un simple compte à rebours. Rien de plus, rien de moins.



        Exécuter du code à intervalle de temps régulier : setInterval()

        La méthode setInterval() va simplement vous permettre d'exécuter votre callback dans un intervalle de temps régulier (comme une horloge). La ou setTimeout() ne s'exécute qu'une seule fois, setInterval() va répéter l'exécution de votre callback à un intervalle de temps donné.

        Cette fonction s'utilise de la même manière que setTimeout() :

        1. premier paramètre : callback
        2. deuxième paramètre : intervalle en millisecondes

        C'est donc seulement la mécanique interne de la fonction qui change.



        Arrêter un timer : clearInterval() et clearTimeout()

        Pour stopper l'exécution d'un timer (bien souvent d'un intervalle), vous pouvez utiliser la fonction clearInterval(). Pour pouvoir réaliser ceci, il va falloir identifier votre timer en l'assignant a une variable. Vous n'aurez plus qu'à passer le nom de la variable en paramètre de la fonction clearInterval() pour que le setInterval() se désactive.

        Exemple :

        <button id="stop">Stop interval</button>
        <script>
        let test = setInterval(function(){
        console.log('ok')
        },250); /* Ceci m'affichera ok dans la console, toutes les 250ms */

        document.getElementById('stop').addEventListener('click', function(){
        clearInterval(test); /* Ceci stoppera l'exécution de mon intervalle */
        })
        </script>

        La fonction clearTimeout() fonctionne de la même manière, mais pour setTimeout().



        Conclusion

        Les timers, bien que très simples, sont extrêmement puissants. Ils sont surtout utilisés pour créer des animations (mouvements, fondus, etc...), et cette compétence est assez peu demandée sur le marché du travail français, car de nombreuses libraires existent déjà. En revanche, le web d'aujourd'hui contient forcément quelques animations, il serait très difficile de s'en passer dans une interface moderne. 

        Les animations sont une introduction fun à la programmation asynchrone, et connaitre leurs mécanismes vous permettra de mieux comprendre le fonctionnement des librairies que vous utiliserez certainement plus tard.

        => Trève de bavardage, à vous de jouer !

      • Requêtes HTTP asynchrones

        Depuis une dizaine d'années, JavaScript permet de faire ce que nous appelons des appels AJAX (pour Asynchronous JAvascript + Xml). Voici pourquoi l'on recourt à cette technique. 

        Quand un utilisateur charge une page web, le serveur lui renvoi une réponse. On parle alors de requête HTTP et de réponse HTTP. Mais une fois que la réponse est reçue par le client, les données utiles contenues dans la page ne sont pas modifiables, à moins de faire une nouvelle requête HTTP au serveur. Sauf qu'avec le web 2.0, le besoin s'est fait grandement sentir de pouvoir récupérer de nouvelles données après que la page soit chargée, sans pour autant être obligé de re-télécharger l'intégralité de la page.

        ajax description

        Imaginez une page web qui affiche le cours de la bourse en direct. Le cours change régulièrement, toutes les 30 secondes disons. Et bien sans appel AJAX, nous serions obligés de rafraîchir toute la page toutes les 30 secondes pour avoir les données mise à jour. Alors que nous, tout ce que nous voulons mettre à jour c'est le nouveau cours de la bourse, et pas l'intégralité du code HTML de la page.

        Grâce aux appels AJAX, basés sur le principe de la programmation asynchrone, on va pouvoir écrire en JavaScript des fonctions qui vont récupérer le petit bout d'info qui nous manque (le cours du dollar par exemple), et on l'affichera au bon endroit dans notre page après réception (par exemple : mettre à jour le graphique du cours de la bourse).

        ajax js jquery

        Cette utilisation de JavaScript a bouleversé la manière dont on fait des sites web. Aujourd'hui, la plupart des sites ou applications web utilisent cette méthode de travail, bien que la technique pour réaliser ça ait évoluée. Historiquement, c'est l'objet XHR qui permettait de mettre en place des appels Ajax. Plus tard, les bibliothèques JavaScript populaires, telles que JQuery, proposaient des méthodes très complètes pour faire de l'AJAX. Aujourd'hui, avec les gros changements qu'ont apportées les versions ES6/7/8 de JS, nous disposons d'outils encore plus fiables et modernes pour réaliser des appels asynchrones, tel que la méthode fetch() des navigateurs.

        Pour conclure sur la présentation, voici un schéma un peu plus détaillé du fonctionnement d'une requête HTTP asynchrone, émise par JavaScript :


        • API : Application Programing Interface

          Maintenant que nous avons découvert le principe d'une requête asynchrone, parlons un peu d'une de sa principale utilité en développement JS front-end. Comme nous l'avons vu, les requêtes AJAX permettent d'aller récupérer des informations sur notre serveur a posteriori. Cela peut être très utile quand certaines parties de votre page web doivent changer de contenu après que l'utilisateur est chargé l'intégralité du document. Il s'avère que ce mode de fonctionnement a donné naissance à un pan entier des modèles d'architecture web : les API, pour Application Programing Interface (interface de programmation applicative).

          Note : une API n'est pas forcément "web". Quand vous utilisez JavaScript pour modifier le DOM, vous utilisez déjà l'API du navigateur. Les API sont partout, elles permettent d'offrir un accès facilité à une entité.

          api

          L'idée d'une API, c'est que l'on va donner un accès protégé aux ressources d'un serveur depuis l'extérieur. Cela peut être votre serveur, ou bien celui d'une plateforme tierce. L'exemple le plus répandu est le service de géolocalisation Google Maps (exemple déprécié : il faut lâcher son numéro de carte bleue désormais. On en verra d'autres). 


          Exemple : le geocoder de GoogleMaps

          Bien qu'étant un site "à part entière", Google Maps vous permet d'utiliser ces services à l'intérieur de votre propre site, via une API dédiée. C’est-à-dire que vous pourrez bénéficier des services qu'offre l'API, et de sa puissance de calcul, pour les besoins de votre projet. 

          Si vous souhaitez transformer une adresse postale en coordonnées GPS exactes, comment feriez-vous ? Cela risque d'être très compliqué... Et bien avec l'API de Google Maps, il vous suffit de lui envoyer l'adresse postale, et il vous retourne des coordonnées GPS précises. Je vous laisse imaginer la complexité de la tâche... Mais vous, vous pouvez bénéficier de ça en quelques lignes de code !


          Pour récupérer de l'information sur un serveur, il suffit donc de requêter une URL via une fonction JavaScript spécialisée, et le serveur renverra des données que vous pourrez exploiter dans votre programme. C'est la technique de base, rentrons maintenant un peu plus dans les détails...
          Important : pour la suite du cours, merci de visiter cette URL : https://jsonplaceholder.typicode.com. C'est une fausse API, qui va nous permettre de nous entrainer. Elle stocke des informations sur des utilisateurs, qui ont chacun des tâches, des albums photos, des articles, etc... TYPICODE EST DOWN DEPUIS PAS LONGTEMPS : FAIRE DES TESTS AVEC https://reqres.in/ OU https://dummyapi.io/


          Paramétrer une requête

          Un des aspects très important des API, c'est que vous allez pouvoir paramétrer vos requêtes. Pour reprendre l'exemple du cours de la bourse, on pourrait imaginer que l'on souhaite récupérer plusieurs cours de devises :

          • le dollar
          • le yen
          • l'euro
          • le CFA
          • le pesos
          • etc...?


          Il va donc falloir paramétrer notre requête, afin de ne récupérer seulement ce que l'on souhaite.


          Récupérer une ressource

          Ouvrez cette URL dans votre navigateur : https://jsonplaceholder.typicode.com/users  

          Note : regardez le users à la fin de l'URL.

          Cette requête va renvoyer la ressource users  offerte par le serveur présent à l'URL https://jsonplaceholder.typicode.com. Et quand on affiche le résultat, on constate qu'on obtient une liste d'utilisateur .


          Rajouter un paramètre

          Ouvrez cette URL dans votre navigateur : https://jsonplaceholder.typicode.com/users/1

          Note : regardez le users/1 à la fin de l'URL.

          Faites le test dans votre navigateur, puis regardez le résultat. On constate ici que notre résultat n'est plus une liste d'utilisateur, mais seulement l'utilisateur ayant l'id 1. Faites le test avec 2, 3, 4... Sympa non ? 


          Conclusion

          On peut requêter avec précision notre serveur. Maintenant, allez jeter un œil sur la doc de l'API, aux onglets ressources et routes de cette page  https://jsonplaceholder.typicode.com/. Vous constaterez que l'on peut paramétrer sa requête de différentes manières, et sur plusieurs ressources (user, post, photo, comment, etc....).

          Important : une API ne renvoie pas de HTML, ou bien rarement. Aujourd'hui les données échangées lors d'un appel asynchrone transit dans un autre format, le format JSON. Nous verrons ça ensemble juste après.



          Les méthodes HTTP

          Il faut savoir que le protocole HTTP, utilisé pour requêter nos serveurs, dispose de 4 méthodes différentes : GET, POST, PUT, DELETE. Ce qui veut dire que vous pouvez requêter la même URL avec ces 4 méthodes, afin de modifier le comportement du serveur selon votre requête. 

          Par exemple, on utilisera :

          • la méthode GET pour récupérer des données
          • la méthode POST pour enregistrer des données
          • la méthode PUT pour modifier des données
          • la méthode DELETE pour supprimer des données


          On peut voir un exemple simple d'utilisation sur la page https://github.com/typicode/jsonplaceholder#how-to, qui nous montre comment utiliser ces différentes méthodes (via un fetch). Le plus souvent, la méthode GET est la plus utilisée, surtout sur des API publiques. Mais si les développeurs de l'API ont prévus des routes d'accès sur des méthodes HTTP différentes, alors il vous faudra les utiliser en paramétrant correctement vos requêtes.


          Types d'API

          Les API peuvent être publiques ou privées. Il est toutefois rare qu'une API soit ouverte "aux quatre vents" comme nous venons de le voir avec jsonplaceholer. La majeure partie du temps, il vous faudra au moins être identifié. Pour ce faire, vous devez vous inscrire sur la plateforme que vous souhaitez utiliser, lire la marche à suivre pour pouvoir utiliser l'API (et en tant que développeur scrupuleux, la doc technique aussi !), puis insérer votre identifiant dans les requêtes, afin que la plateforme vous reconnaisse en tant qu'utilisateur autorisé. 

          Bien souvent, ce mode d'accès la vous permet d'utiliser une API gratuitement, et "en bon père de famille", en limitant vos accès via des quotas d'utilisation (ex : 10000 requêtes par jour max). Le plus souvent, ces API vous proposerons une offre Premium si votre site dépasse les limites de l'offre gratuite. Certaines sont payante d'entrée, tout dépend du service proposé.
          Tous les grands noms d'Internet proposent des services via une API publique (plateforme de streaming, météo, réseaux sociaux, bourse, etc... la liste est longue).


          Types d'applications

          Dans certains projets, vous verrez que l'API du serveur est le point central entre le front et le back. Purement privé, ces API résultent d'un choix technique d'architecture. Et cela peut être bien pratique pour de nombreuses raison :

          • séparation totale du back et du front
          • utilisation de l'API via différents supports (navigateurs, applis mobiles, informatique embarqué, ...)
          • mise à disposition de ressources pour les clients
          • etc...


          Voici un exemple de fonctionnement d'une API pour un site de réservation d'avion :

          api rest javascript


          • Le format JSON

            Le format JSON, pour JavaScript Object Notation, est un format de fichier permettant de représenter de l'information sous forme de texte structuré. Un fichier JSON est une chaîne de caractère plus ou moins longue selon la quantité de données qu'elle représente. En revanche, ça n'est pas un texte "libre", c'est une structuration de type clé/valeur récursive, qui permet de définir des propriétés et leurs valeurs, comme sur un objet figé.

            Il existe d'autres format de structuration de données tel que XML ou YAML, mais quand on fait de l'AJAX, c'est bien souvent JSON qui servira de format d'échange de données entre le client et le serveur (surtout aujourd’hui). Donc JSON est vraiment la norme lorsque l'on parle d'AJAX. Le format JSON peut aussi être utilisé dans d'autres cas de figures, tel que des fichiers de configuration par exemple. La dernière version des spécifications du format date de décembre 2017. Des bibliothèques pour le format JSON existent dans la plupart des langages de programmation.

            Logo JSON



            Voici un exemple de chaîne JSON :

            [ { id: 1, name: "Leanne Graham", username: "Bret", email: "Sincere@april.biz", address: { street: "Kulas Light", suite: "Apt. 556", city: "Gwenborough", zipcode: "92998-3874", geo: { lat: "-37.3159", lng: "81.1496" } }, phone: "1-770-736-8031 x56442", website: "hildegard.org", company: { name: "Romaguera-Crona", catchPhrase: "Multi-layered client-server neural-net", bs: "harness real-time e-markets" } }, { id: 2, name: "Ervin Howell", username: .............. cela peut-être très looooooong ^^ ...................................... ......"e-enable extensible e-tailers" } }, { id: 9, name: "Glenna Reichert", username: "Delphine", email: "Chaim_McDermott@dana.io", address: { street: "Dayna Park", suite: "Suite 449", city: "Bartholomebury", zipcode: "76495-3109", geo: { lat: "24.6463", lng: "-168.8889" } }, phone: "(775)976-6794 x41206", website: "conrad.com", company: { name: "Yost and Sons", catchPhrase: "Switchable contextually-based project", bs: "aggregate real-time technologies" } }, { id: 10, name: "Clementina DuBuque", username: "Moriah.Stanton", email: "Rey.Padberg@karina.biz", address: { street: "Kattie Turnpike", suite: "Suite 198", city: "Lebsackbury", zipcode: "31428-2261", geo: { lat: "-38.2386", lng: "57.2232" } }, phone: "024-648-3804", website: "ambrose.net", company: { name: "Hoeger LLC", catchPhrase: "Centralized empowering task-force", bs: "target end-to-end models" } } ]


            Assez illisible, n'est-ce pas ? :)

            Maintenant, ouvrez cette URL dans votre navigateur préféré : https://jsonplaceholder.typicode.com/users

            Si vous avez un navigateur moderne, vous devriez voir quelque chose comme ceci (si ça n'est pas le cas, installez un plugin de type "json viewer" (ex : Json View dans Chrome)) :


            Ah, c'est de suite plus agréable à lire ! Et on voit bien l'idée du JSON : une norme qui permet de structurer des données en utilisant les différents types provenant de la programmation : 

            • entier
            • chaîne de caractères
            • booléen
            • tableaux
            • objets
            • ...


            Autres exemple de fichiers JSON à commenter


            Note : lorsque vous créerez vous-même vos chaînes JSON, vous pouvez vous appuyer sur des validateurs qui vous diront si votre JSON est correctement formaté (ex : https://www.jsonschemavalidator.net/). Ne vous inquiétez pas, la plupart du temps c'est votre application qui construit votre JSON, vous n'avez pas à le faire à la main. Sauf dans certains cas, tel que les objets d'options ou de configuration (qui sont assez court en général).


            Conversions
            Quand on travaille avec du JSON, on va vouloir utiliser les données présentes dans une chaîne JSON, en variable de notre programme. Ne serait-ce que pour les afficher, il va bien falloir les traiter à l'aide d'un langage de programmation. On utilisera alors des fonctions natives pour passer de la chaîne JSON à une variable contenant toutes nos données. Et inversement, on va vouloir transformer une variable contenant des informations en chaîne JSON.

            Voici les termes fréquemment utilisés pour passer de l'un à l'autre :
            • transformer un JSON en variable : JSON.parse(), json_decode() (PHP), res.json(), etc...
            • transformer une variable en JSON (on parle alors de sérialisation) : JSON.stringify(), json_encode() (PHP), etc...


            Et voici un schéma illustrant ou se trouve votre JSON dans le processus de requête asynchrone :



            Conclusion
            Alors qu'avec HTML/CSS on décrit la structure, le sens, l'apparence ou le contenu d'une page web, avec JSON on a seulement les données brutes (dans le sens dynamique du terme). Celles qui font que la page de profil de Jacques et différente de celle de Paul. Et ceci est très intéressant, car on va pouvoir définir un squelette statique avec HTML/CSS, et venir insérer des données dynamiques à l'intérieur, à l'aide de JS, des appels asynchrones, et de JSON !

            C'est une façon très répandue de travailler aujourd'hui, et cela comporte plusieurs intérêts :
            • légèreté des échanges avec le serveur : un JSON est moins lourd qu'une page HTML complète, vu qu'il ne comporte que les données utiles. On parlera alors de payload (charge utile en français)
            • meilleure séparation du code, des données, et de toute la structure et l'apparence de la page : code plus facile à comprendre et à maintenir



          • XHR et JQuery

            Note : cette section est là à titre historique, afin de comprendre l'évolution des appels asynchrones en développement web. L'objet XHR est actuellement déprécié, donc inutile de le maitriser correctement.


            Comme nous l'avons vu dans la présentation, un des principaux problème de l'architecture client/serveur du web est que lorsque nous avons chargé une page web, celle ci est statique, et nous ne pouvons pas récupérer d'autres données provenant du serveur à moins de faire une nouvelle requête HTTP (donc : charger une nouvelle page). Et bien grâce à l'AJAX, nous pouvons désormais récupérer des données provenant d'un serveur après que notre page soit chargée.

            Voici une représentation schématique d'un appel AJAX standard :


            C'est très similaire à une requête HTTP classique, la différence est dans le contenu des données échangées, et bien sur dans le fait qu'un appel AJAX fonctionne de manière asynchrone. Le JS est exécuté, et on attends la réponse du serveur avant de modifier le DOM


            Nous allons voir ici deux méthodes qui seront de moins en moins utilisées dans les temps qui viennent, mais qui sont toujours utilisées de nos jours. Donc nous ne les utiliserons pas forcément par la suite, mais je tiens à vous les montrer car vous pourriez bien les croiser en entreprise.


            L'objet XHR

            Au même titre que l'objet Date ou l'objet Math de JS, l'objet XHR est un objet disponible nativement dans JS et les navigateur. Il a pour but de faire de l'échange de données entre client et serveur de manière asynchrone, en utilisant le format XML. Voici un exemple d'implémentation, pour aller chercher une liste d'utilisateurs. La liste d'utilisateur est fournie par un service gratuit qui permet de s’entraîner à faire des requêtes asynchrone. Dans cet exemple, nous allons écrire une fonction qui aura la charge de requêter une URL et d'afficher le résultat obtenu dans la console. Pensez bien à mettre ça entre les deux console.log de début et de fin dans votre sandbox.


            Ecrivez ce code dans votre sandbox :

            objet XHR js


            Une fois que c'est fait, aller voir ce qu'il se passe dans votre console. Vous devriez récupérer une liste d'utilisateurs, contenue dans la propriété "response" de votre variable "req" :

            js xhr response


            Cette méthode, bien qu'efficace, ne prends pas de callback en considération, elle ne fait qu'exécuter du code sur un événement de l'objet XHR. L’inconvénient, c'est que vous allez devoir écrire tout ça à chaque fois que vous devrez récupérer des données. C'est un peu fastidieux. Donc reformatons notre fonction ajax(), afin qu'elle prenne en compte des fonctions de rappels, et qu'elle devienne beaucoup plus générique :

            js xhr async + callback

            Nous pouvons voir dans cet exemple (ligne 26 et 27), que ce sont bien nos paramètres de fonctions "success" et "error" qui sont appelés. Sauf que success et error sont des fonctions. Ce sont les fonctions qu'on a "envoyé" dans notre appel de fonctions ajax() ligne 35 et 37. Donc dans cet exemple, les fonctions anonymes success et error ne seront appelées que après que l'objet XHR est émis l'événement onreadystatechange (ligne 23). De plus, elles seront rappelées avec un paramètre (ligne 26 et 28), et le paramètre est bien prévu dans nos fonctions de rappels (ligne 35 et 37). 

            Ici, ce paramètre représentera :

            • soit la "charge utile" (les données que nous venons de recevoir de la part du serveur)
            • soit l'objet XHR contenant l'erreur

            Pour conclure : je pourrai utiliser la fonction ajax() avec différentes URL, et différentes fonctions de rappel.


            Jquery

            Pendant un bon moment, JQuery régnait en maître sur les différentes bibliothèque Javascript. Et un de ses principaux avantages était qu'il offrait une manière facile et pratique de faire des appels Ajax, sans coder soit même des fonctions utilisant l'objet XHR. Voici un exemple d'implémentation d'une des méthodes de Jquery permettant de faire de l'ajax :

            ajax et jquery

            N'oubliez pas d'appeler JQuery dans votre sandbox pour pouvoir faire ça. Pour ceux qui ne connaissent pas JQuery, la ligne 45 est l'équivalent de l’événement "attendre que le DOM soit chargé". On en a besoin ici, car pour utiliser une fonction de JQuery, il faut bien attendre que la bibliothèque soit correctement chargée dans le navigateur. 

            Recopiez ce code dans votre sand box, et faites les test afin d'avoir la liste des utilisateurs dans votre console. 

            Vous devriez obtenir ceci :

            jquery ajax json


            Explication du code :

            • ligne 46 : appel de la méthode ajax() de l'objet $ (JQuery), définition de l'url sur laquelle on veux récupérer des données.
            • ligne 47 : définition du type de données que l'on va traiter. Cette option permet à JQuery d'effectuer une série d'opération sur le résultat obtenu pour transformer la chaîne JSON des utilisateurs en variable JS directement utilisable par la suite (tableau, chaîne, nombre, etc...).
            • ligne 48, 49, 50 : callback success. Ce sera la fonction qui sera appelée par JQuery si tout se passe bien.
            • ligne 51, 52, 53 : callback erreur. Ce sera la fonction appelée par JQuery si il y a une erreur.

            • Callback Hell

              En revanche, la syntaxe qui permet d'écrire du code asynchrone n'est pas toujours adaptée, et dans certains cas, un programme asynchrone peut vite devenir illisible car trop enchevêtré. De nouvelles syntaxes, et de nouveaux mot clés ont fait leur apparitions en Javascript pour permettre une écriture du code plus "propre", mais comme nous l'avons vu dans les cours précédents, il y a toujours un usage "à l'ancienne", un usage "à la pointe", et 50 nuances de JS entre les deux... Nous parlerons de la majorité des méthodes disponibles pendant la théorie, mais en pratique, nous utiliserons les techniques actuelles durant la formation.


              • Promesses

                Les promesses sont un nouvel objet introduit dans ES6. Elles permettent de faire de l'asynchrone de manière plus propre et de se rapprocher de l'écriture de code synchrone. On les déclare de la même manière qu'un nouvel objet, en utilisant la classe Promise. En revanche, comme nous sommes en asynchrone, nous allons utiliser les callback dans son constructeur. Ce callback comprends deux paramètres, qui sont les fonctions resolve() et reject().

                Les promesses ont deux particularités :

                • soit elles sont "tenues", on exécutera donc une fonction resolve() pour déterminer cet état
                • soit elles ne sont pas tenues (il y a eu une erreur), et on utilisera la fonction reject() pour signifier cela


                Le fait d'utiliser ces fonctions à l’intérieur de notre promesse est un peu comme si on retournait notre résultat via le mot clé return. Donc quand on aura le résultat attendu, on utilisera la fonction resolve() avec le résultat (ex : resolve(resultat) ). Et quand on détectera un problème, on pourra utiliser la fonction reject() de la même manière.

                Ces fonctions resolve() et reject(), vont nous permettre de pouvoir chaîner plusieurs fonctions asynchrones les unes à la suite des autres, et d'attraper l'erreur s’il y a lieu.

                Nous ne nous attarderons pas dessus, car pour l'instant nous les utiliserons surtout via l'API fetch qui est conçue avec ce nouvel objet Promise. Voyons tout de même comment cela fonctionne sans passer par fetch().


                Recopiez ce code dans votre sandbox :

                function attendre(ms) {
                let attente = new Promise(function(resolve, reject) {

                setTimeout(function() {
                resolve(`Le temps d'attente est ${ms} millisecondes`);
                }, ms);

                setTimeout(function() {
                reject(`Le temps d'attente est trop long`);
                }, 3000);

                });

                return attente;
                }

                function affiche(message) {
                console.log(message);
                }

                function tropLong(message) {
                console.error(message);
                }

                attendre(1000).then(affiche).catch(tropLong);

                Analyse du code :

                • l.208 : on appel notre fonction attendre, avec 1000 comme paramètre
                • l.185 : la fonction attendre instancie une nouvelle promesse (avec ses deux callback)
                • l.187-189 : on met en place le timer avec le paramètre de l'utilisateur (ms = 1000). Quand ce timer sera arrivé à terme, on exécute le resolve() avec le message à retourner
                • l.191-193 : on met en place un deuxième timer, qui lui est réglé à 3 secondes. Quand ce timer arrive à son terme, on appel la fonction reject() avec le message d'erreur à retourner
                • l.197 : on retourne notre promesse
                • l.208 : on chaîne notre première fonction avec la fonction de succès, c'est la méthode .then() ( .then(affiche) )
                • l.200 : la fonction affiche() est appelée seulement en cas de succès, et reçoit la valeur de retour du resolve de la promesse de la fonction attendre, puis l'affiche
                • l.208 : on chaîne notre erreur grâce à la méthode catch() ( .catch(tropLong) ), qui exécutera la fonction tropLong() en cas de reject()
                • l.204 la fonction tropLong() reçoit le message d'erreur puis l'affiche


                Pour faire les tests, passer votre premier paramètre (1000), à 4000 pour voir.


                Donc pour conclure, les promesses remplaceront peu à peu l'objet XHR côté front. La différence avec XHR, c'est que le XHR était conçu pour faire des requêtes asynchrones entre le client et le serveur (pour faire de l'AJAX). Alors que les promesses peuvent faire de l'asynchrone "tout court". Et elles sont très utilisées dans les serveurs NodeJS, en back-end. Node est entièrement conçu en asynchrone, il fallait donc une solution technique plus propre que de simple callback pour programmer en Node.

                Coté front, c'est la méthode fetch() qui est maintenant à utiliser en priorité sur les appels AJAX "classiques", et celle-ci fonctionne grâce aux promesses. Vous retrouverez donc la même structure que les promesses dans les fetch().
                • La méthode fetch

                  La méthode fetch() disponible en Javascript permet de faire des requêtes sur des des ressources de manière plus optimisée que l'objet XHR. La méthode fetch() se base sur le nouvel objet Promise (promesse), introduit en JS depuis l'ES6. La grande différence avec l'objet XHR, c'est que vous allez pouvoir "chaîner" vos callback de succès ou d'erreur directement à la suite de votre fetch() via les mots clés .then() et .catch()

                  1. le then représente ce que vous voulez faire en cas de succès. Il prends en paramètre une fonction anonyme, qui elle même prend un paramètre qui sera le retour de votre fetch() (votre résultat).
                  2. le catch représente votre callback d'erreur, avec un callback et son paramètre qui est le message d'erreur


                  Il fonctionne de manière assez simple, voici comment ça se présente :

                  fetch javascript


                  Ecrivez ce code dans votre sandbox, puis analysons le ensemble :

                  • l. 62 : appel de l'url via la méthode fetch, et mise en place du callback de succès avec envoi du résultat
                  • l. 63-64 : traitement sur le résultat, utilisation de la méthode .json() pour transformer notre résultat JSON en variable JS
                  • l. 65 : la fonction json() renvoyant une promesse, mise en place d'un nouveau .then() pour récupérer le résultat une fois que l'opération est finie via le paramètre data
                  • l. 66-67 : traitement final de notre liste d'utilisateur. Ici un simple console.log, mais on pourrait imaginer qu'on les affiche dans le DOM.
                  • l. 69-71 : mise en place du catch en cas d'erreur


                  Attention : nous sommes en programmation asynchrone, donc si vous débuguer "data", à l’extérieur de votre fetch, il y a de forte chance pour qu'il soit vide. C'est très important de comprendre ça. Pensez qu'un appel asynchrone est une sorte d'espace temps différent à l'intérieur de votre programme. Mettez en place ce test histoire de bien vous en rendre compte, ici le data à l'extérieur du fetch (l. 61 et 73) n'est pas le data à l'intérieur (l. 67) !




                  Paramétrer les options du fetch

                  Vous pouvez changer certaines options du fetch() en lui envoyant un objet en paramètre. Si par exemple vous voulez créer un nouvel article (post), vous allez devoir utiliser la méthode POST de votre route au lieu de la GET, et lui envoyer les données à enregistrer pour votre nouvel article. Dans cet exemple, l'API retourne simplement l'Id du nouvel article faussement créé (nous sommes en test) :

                  js fetch post


                  Ici, on peux voir que la méthode fetch() prend un paramètre supplémentaire, qui contient des options de paramétrage. On y distingue la méthode choisie (POST : l. 90), et les données à "joindre" à notre requête, via la propriété "body" (les données de notre nouvel article)(l. 91-95).

                • async / await

                  Les async/await sont une nouvelles syntaxes permettant d'écrire du code asynchrone de la même manière que du code synchrone (c'est à dire, sans callback dans des callback, dans des callback...).

                  Extrait de code :


                  //ASYNC / AWAIT
                  //Fonction SANS async
                  function request_normale() {
                    fetch('https://jsonplaceholder.typicode.com/users')
                      .then(response => response.json())
                      .then(json => console.log(json))
                  }
                  //Fonction AVEC async
                  async function request_async() {
                    let response = await fetch('https://jsonplaceholder.typicode.com/users');
                    let json = await response.json();
                    console.log(json);
                  }
                  request_normale();
                  request_async();


                  https://www.supinfo.com/articles/single/5640-programmation-asynchrone-javascript