Nous faisons des requêtes HTTP, dégradons gracieusement (et pas un seul écart)

image

Aujourd'hui, peu de gens se souviennent que les applications Web peuvent s'exécuter sans une seule demande XHR. AJAX (Javascript asynchrone et XML) fournit une fonctionnalité intéressante - charger des données sans recharger la page. Ce concept est à la base de la plupart des SPA modernes.

Mais rien n'est donné comme ça, il faut tout payer. Le concept AJAX semble extrêmement simple, mais même au niveau de la demande de données au serveur, vous pouvez rencontrer beaucoup de problèmes.

Pour commencer, écrivons l'application SPA la plus simple avec AJAX:

initApp(); function initApp() { document.body.innerHTML = ` <h3>Employees list</h3> <ul id="employees-list"></ul> <button id="load-employees">Load employee</button> `; document.getElementById('load-employees').addEventListener('click', loadEmployee); } function loadEmployee() { fetch('http://dummy.restapiexample.com/api/v1/employee/1') .then(res => res.json()).then(({employee_name}) => addEmployee(employee_name)); } function addEmployee(employeeName) { const employeeElement = document.createElement('li'); employeeElement.innerText = employeeName; document.getElementById('employees-list').appendChild(employeeElement); } 

Tout est extrêmement simple: lorsque vous cliquez sur le bouton, nous demandons des données au serveur et lorsqu'elles sont reçues, ajoutez l'élément à la liste.

Comme je l'ai dit, à ce stade, beaucoup de choses peuvent mal tourner et, afin d'approfondir le sujet, nous allons d'abord analyser un peu de théorie.

Deux principes de construction d'interfaces tolérantes aux pannes


image

Dégradation gracieuse


Il s'agit de la philosophie de conception d'interface dans laquelle l'utilisateur dispose initialement d'autant de fonctions que possible. Et ce n'est qu'en cas de défaillance d'une partie du système que les fonctions qui en dépendent sont désactivées. Cela semble compliqué, mais ci-dessous, nous allons l'analyser avec un exemple - ce sera beaucoup plus clair.

Amélioration progressive


Il existe une philosophie alternative / parallèle - l'amélioration progressive. Dans ce document, le mouvement va dans l'autre sens: initialement, l'utilisateur dispose d'un ensemble minimal (ou moyen) de fonctionnalités. Et pour initialiser le reste, le support des pièces du système nécessaires à leur travail est d'abord vérifié.

Habituellement, lorsque l'on parle de dégradation gracieuse et d'amélioration progressive dans le contexte d'applications basées sur un navigateur, elles signifient une compatibilité ou une adaptabilité entre les navigateurs. Il existe un exemple populaire expliquant ces concepts. Supposons que votre application dispose d'une fonction d'impression de page, et si vous le faites:

 <body> <a href="javascript:window.print()" id="print-btn">Print</a> <script> const printButton = document.getElementById('print-btn'); if (printButton && typeof window.print !== 'function') { printButton.parentNode.appendChild(document.createTextNode('  ')); printButton.parentNode.removeChild(printButton); } </script> </body> 

c'est alors une dégradation gracieuse , car vous affichez immédiatement le bouton d'impression, mais lorsque vous réalisez que l'impression n'est pas prise en charge par le navigateur, vous supprimez la fonctionnalité.

PS: Dans l'exemple d'origine, la balise noscript a été utilisée pour démontrer une dégradation gracieuse , mais elle me semble très dépassée.

Si vous faites ceci:

 if(typeof window.print === 'function') { const printButton = document.createElement('a'); printButton.innerText = 'Print'; printButton.addEventListener('click', () => window.print()); document.body.appendChild(printButton); } 

il s'agit d'une amélioration progressive , car vous vérifiez d'abord la prise en charge de l'API requise, puis vous ajoutez la fonction.

Les exemples montrent l'application la plus primitive des philosophies de conception d'interface de tolérance aux pannes.

Retour aux requêtes AJAX et HTTP .

Qu'est-ce qui pourrait mal tourner avec AJAX?


Code d'état HTTP inattendu


image

Le cas le plus simple sera si le serveur renvoie le mauvais code d'état que vous attendiez, disons 500. Il s'agit d'un scénario courant et vous disposez probablement de quelques outils pour le traiter. Par exemple, affichez à l'utilisateur une notification «Une erreur de serveur s'est produite». C'est clairement une dégradation, mais est-ce gracieux? Est-il possible d'appliquer ici une amélioration progressive? Non, ce n'est certainement pas le lieu d'une amélioration progressive - la fonctionnalité s'est déjà dégradée. Vous ne pouvez que vaincre ce problème magnifiquement:

  1. Découvrir que cette situation s'est généralement produite chez le client afin de l'empêcher à l'avenir Pour cela, des enregistreurs d'erreurs sont généralement utilisés, par exemple sentry.io .
  2. Si possible, mettez en cache les données reçues. Cool s'il y avait déjà un appel à une demande similaire et que vous avez mis en cache les données. Dans ce cas, même si vous recevez un code d'état inattendu du serveur, vous pouvez afficher l'interface, mais pas avec les données les plus récentes.
  3. Essayez de réessayer la demande ultérieurement. Il s'agit peut-être d'un plantage temporaire du serveur et, après quelques secondes, il "sortira". Vous pouvez soit faire une deuxième demande automatiquement ou fournir cette option à l'utilisateur.
  4. Ne bloquez pas le reste de l'application. Si vous montrez un spinner ou un squelette avant d'appeler la requête HTTP, n'oubliez pas de le masquer à la fin de la requête, réussie ou non. Cela peut sembler évident, mais je l'ai rencontré assez souvent.
  5. En général, il peut y avoir de nombreux codes d'état inattendus, par exemple, lorsqu'une session utilisateur a expiré et que le serveur a répondu avec le code 403. Pour cette erreur, un gestionnaire distinct est requis qui réémet le jeton de session ou envoie l'utilisateur pour autorisation. L'application de basculement doit avoir des gestionnaires pour toutes les réponses de serveur possibles.

Réponse invalide


image

Ne faites jamais confiance au backend! Le serveur peut répondre avec le code 200, mais dans le corps de la réponse, il renverra les mauvaises données dont vous avez besoin. Dans cette situation, vous pouvez faire la même chose qu'avec un code d'état inattendu, mais la difficulté est de déterminer que la réponse est vraiment invalide.

Si vous écrivez en tapuscrit, alors pour vous il y a un outil sympa - typescript-json-schema . Avec lui, vous pouvez générer des schémas json à partir d'interfaces dactylographiées et les utiliser pour valider les données lors de l'exécution.

Réponse longue


image

C'est le coup auquel peu de gens s'attendent. Si nous nous souvenons d'erreurs ou même de données de réponse invalides, nous nous souvenons rarement des délais d'attente. Le coupable peut être non seulement l'application serveur, mais même le fournisseur d'accès Internet ou l'appareil client.

N'oubliez pas, il vaut mieux informer l'utilisateur que la demande est plus longue que d'habitude que de le laisser face à face avec un cercle tournant sur l'écran. Lorsque le temps imparti pour l'exécution de la demande expire, vous pouvez suivre un scénario similaire à celui des deux situations précédentes.

Manque d'Internet


image

J'ai été très impressionné d'apprendre que Google Documents dispose d'un mode hors ligne. Cela m'a beaucoup aidé lorsque j'ai décidé de terminer la rédaction d'un article dans un avion où il n'y avait pas d'Internet.

Bien sûr, les applications sont différentes et beaucoup d'entre elles sont pratiquement inutiles sans Internet. Mais même dans ces applications, vous pouvez gérer le cas avec le manque de connexion et afficher un message informatif (bien que j'aime aussi jouer au tyrannosaure dans "Chrome").

De plus, vous pouvez écouter les événements qui connectent / déconnectent la connexion Internet . Et, par exemple, rechargez automatiquement les données lors de l'événement en ligne sur la fenêtre.

Interface tolérante aux pannes - ce n'est pas facile


Au total, la liste des actions qui doivent être implémentées lors de l'appel de la requête HTTP:

  1. Erreurs de journal.
  2. Mettez les données en cache et utilisez-les.
  3. Répétez les demandes infructueuses.
  4. Ne bloquez pas l'interface.
  5. Gérez toutes les réponses possibles du serveur.
  6. Validez les réponses du serveur.
  7. Définissez des délais.
  8. Mode hors ligne (manque d'Internet).

Ce qui semblait insignifiant au début s'est transformé en une philosophie entière avec de nombreux problèmes. Bien sûr, ce n'est pas une bannière générique. Mais si votre application a atteint un haut niveau de maturité et que vous souhaitez créer une interface de très haute qualité, c'est dans cette direction qu'elle mérite d'être développée.

Le but de cet article est de parler des problèmes possibles lors de l'utilisation de requêtes HTTP, mais pas de solutions spécifiques. Il existe aujourd'hui un grand nombre de bibliothèques et de frameworks qui visent à résoudre ces problèmes, par exemple les intercepteurs HTTP dans Angular.
Connaissant les problèmes possibles, il sera beaucoup plus facile de trouver une solution pour eux sur Internet.

Source: https://habr.com/ru/post/fr483756/


All Articles