Fazemos solicitações HTTP, degradamos normalmente (e não uma única lacuna)

imagem

Hoje, poucas pessoas lembram que os aplicativos da Web podem ser executados sem uma única solicitação XHR. O AJAX (Javascript assíncrono e XML) fornece um recurso interessante - carregamento de dados sem recarregar a página. Este conceito é subjacente à maioria dos SPA modernos.

Mas nada é dado assim, você tem que pagar por tudo. O conceito AJAX parece extremamente simples, mas mesmo no nível de solicitação de dados do servidor, você pode encontrar muitos problemas.

Para começar, vamos escrever o aplicativo SPA mais simples com o 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); } 

Tudo é extremamente simples: quando você clica no botão, solicitamos dados do servidor e, quando recebidos, adicionamos o item à lista.

Como eu disse, nesta fase, muita coisa pode dar errado e, para expandir o tópico mais profundamente, primeiro analisaremos um pouco de teoria.

Duas filosofia de construção de interfaces tolerantes a falhas


imagem

Degradação graciosa


Essa é a filosofia de design de interface na qual o usuário recebe inicialmente o maior número possível de funções. E somente no caso de falha de qualquer parte do sistema, as funções dependentes dele serão desativadas. Parece complicado, mas a seguir vamos analisá-lo com um exemplo - será muito mais claro.

Aprimoramento progressivo


Existe uma filosofia alternativa / paralela - aprimoramento progressivo. Nele, o movimento é contrário: inicialmente, o usuário recebe um conjunto mínimo (ou médio) de funcionalidades. E para inicializar o restante, primeiro é verificado o suporte das partes do sistema necessárias para o trabalho delas.

Geralmente, quando se fala em degradação simples e aprimoramento progressivo no contexto de aplicativos baseados em navegador, eles significam compatibilidade ou adaptabilidade entre navegadores. Há um exemplo popular explicando esses conceitos. Suponha que seu aplicativo tenha uma função de impressão de página e se você fizer isso:

 <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> 

isso é degradação normal , porque você mostra imediatamente o botão de impressão, mas quando percebe que a impressão não é suportada pelo navegador, você remove a funcionalidade.

PS: No exemplo original, a tag noscript foi usada para demonstrar degradação graciosa , mas parece-me muito desatualizada.

Se você fizer isso:

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

esse é um aprimoramento progressivo , porque primeiro você verifica o suporte para a API necessária e depois adiciona a função.

Os exemplos demonstram a aplicação mais primitiva das filosofias de design de interface de tolerância a falhas.

Voltar para solicitações AJAX e HTTP .

O que poderia dar errado com o AJAX?


Código de status HTTP inesperado


imagem

O caso mais simples será se o servidor retornar o código de status errado que você esperava, digamos 500. Esse é um cenário comum e você provavelmente possui algumas ferramentas para processá-lo. Por exemplo, mostre ao usuário uma notificação "Ocorreu um erro no servidor". Isso é claramente degradação, mas como é gracioso? É possível aplicar aprimoramento progressivo aqui? Não, esse definitivamente não é o lugar para aprimoramentos progressivos - a funcionalidade já está degradada. Você só pode superar esse problema lindamente:

  1. Descobrir que essa situação geralmente ocorreu no cliente para evitá-la no futuro. Para isso, geralmente são usados ​​registradores de erros, por exemplo sentry.io .
  2. Coloque em cache os dados recebidos, se possível. Legal se já houve uma chamada para uma solicitação semelhante e você armazenou os dados em cache. Nesse caso, mesmo se você receber um código de status inesperado do servidor, poderá exibir a interface, embora não com os dados mais atuais.
  3. Tente repetir a solicitação mais tarde. Talvez seja um travamento temporário do servidor e após alguns segundos ele será "liberado". Você pode fazer uma segunda solicitação automaticamente ou fornecer essa opção ao usuário.
  4. Não bloqueie o restante do aplicativo. Se você mostrar um botão giratório ou esqueleto antes de chamar a solicitação HTTP, não esqueça de ocultá-lo em qualquer conclusão da solicitação, com êxito ou não. Isso pode parecer óbvio, mas eu já me deparei com isso com bastante frequência.
  5. Em geral, pode haver muitos códigos de status inesperados, por exemplo, quando uma sessão do usuário expirou e o servidor respondeu com o código 403. Para esse erro, é necessário um manipulador separado que emita novamente o token da sessão ou envia o usuário para autorização. O aplicativo de failover deve ter manipuladores para todas as respostas possíveis do servidor.

Resposta inválida


imagem

Nunca confie no back-end! O servidor pode responder com o código 200, mas no corpo da resposta ele retornará os dados incorretos que você precisa. Nessa situação, você pode fazer o mesmo que com um código de status inesperado, mas a dificuldade está em determinar que a resposta é realmente inválida.

Se você escreve em texto datilografado, existe para você uma ferramenta interessante - typescript-json-schema . Com ele, você pode gerar esquemas json a partir de interfaces datilografadas e usá-los para validar dados em tempo de execução.

Resposta longa


imagem

Este é o golpe que poucos esperam. Se nos lembramos de erros ou mesmo de dados de resposta inválidos, raramente nos lembramos de tempos limites. O culpado pode não ser apenas o aplicativo do servidor, mas também o provedor da Internet ou o dispositivo do cliente.

Não se esqueça, é melhor notificar o usuário que a solicitação é mais longa do que o normal do que deixá-lo sozinho com um círculo giratório na tela. Quando o tempo alocado para a execução da solicitação expirar, você poderá passar por um cenário semelhante ao das duas situações anteriores.

Falta de internet


imagem

Fiquei muito impressionado ao saber que o Google Documents tem um modo offline. Isso me ajudou muito quando decidi terminar de escrever um artigo em um avião onde não havia internet.

Obviamente, os aplicativos são diferentes e muitos deles são praticamente inúteis sem a Internet. Mas mesmo nesses aplicativos, você pode lidar com o caso com a falta de conexão e mostrar uma mensagem informativa (embora eu também goste de tocar o tiranossauro no "Chrome").

Além disso, você pode ouvir eventos conectando / desconectando a conexão com a Internet . E, por exemplo, recarregue automaticamente os dados durante o evento online na janela.

Interface tolerante a falhas - não é fácil


No total, a lista de ações que devem ser implementadas ao chamar a solicitação HTTP:

  1. Erros de log.
  2. Cache de dados e usá-lo.
  3. Repita solicitações sem êxito.
  4. Não bloqueie a interface.
  5. Manipule todas as respostas possíveis do servidor.
  6. Valide as respostas do servidor.
  7. Definir tempos limite.
  8. Modo offline (falta de internet).

O que parecia trivial a princípio se transformou em uma filosofia inteira com muitos problemas. Claro, isso não é um cabeçalho. Mas se seu aplicativo alcançou um alto nível de maturidade e você deseja criar uma interface realmente de alta qualidade, então é nessa direção que vale a pena desenvolver.

O objetivo deste artigo é falar sobre possíveis problemas ao trabalhar com solicitações HTTP, mas não sobre soluções específicas. Atualmente, há um grande número de bibliotecas e estruturas destinadas a solucionar esses problemas, por exemplo, interceptores HTTP no Angular.
Sabendo dos possíveis problemas, será muito mais fácil encontrar uma solução para eles na Internet.

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


All Articles