
Hoy, pocas personas recuerdan que las aplicaciones web pueden ejecutarse sin una sola solicitud XHR. AJAX (Javascript asíncrono y XML) proporciona una característica interesante: cargar datos sin volver a cargar la página. Este concepto subyace a la mayoría de los SPA modernos.
Pero nada se da así, tienes que pagar por todo. El concepto de AJAX parece extremadamente simple, pero incluso al nivel de solicitar datos del servidor, puede encontrar muchos problemas.
Para comenzar, escriba la aplicación SPA más simple con 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); }
Todo es extremadamente simple: cuando hace clic en el botón, solicitamos datos del servidor y cuando se reciben, agregue el elemento a la lista.
Como dije, en esta etapa, muchas cosas pueden salir mal y, para ampliar el tema más profundamente, primero analizaremos una pequeña teoría.
Dos filosofías de construir interfaces tolerantes a fallas

Degradación elegante
Esta es la filosofía de diseño de la interfaz en la que al usuario se le proporcionan inicialmente tantas funciones como sea posible. Y solo en el caso de una falla de cualquier parte del sistema, las funciones que dependen de él están deshabilitadas. Suena complicado, pero a continuación lo analizaremos con un ejemplo: será mucho más claro.
Mejora progresiva
Existe una filosofía alternativa / paralela: mejora progresiva. En él, el movimiento va para otro lado: inicialmente, el usuario cuenta con un conjunto mínimo (o promedio) de funcionalidades. Y para inicializar el resto, primero se verifica el soporte de las partes del sistema necesarias para su trabajo.
Por lo general, cuando se habla de
degradación elegante y mejora progresiva en el contexto de las aplicaciones basadas en navegador, significan compatibilidad o adaptabilidad entre navegadores. Hay un ejemplo popular que explica estos conceptos. Suponga que su aplicación tiene una función de impresión de página, y si hace esto:
<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>
entonces esto es una
degradación elegante , porque inmediatamente muestra el botón de impresión, pero cuando se da cuenta de que el navegador no admite la impresión, elimina la funcionalidad.
PD: En el ejemplo original, la etiqueta noscript se usó para demostrar una
degradación elegante , pero me parece muy anticuada.
Si haces esto:
if(typeof window.print === 'function') { const printButton = document.createElement('a'); printButton.innerText = 'Print'; printButton.addEventListener('click', () => window.print()); document.body.appendChild(printButton); }
esta es una
mejora progresiva , porque primero verifica el soporte para la API requerida y solo luego agrega la función.
Los ejemplos demuestran la aplicación más primitiva de las filosofías de diseño de interfaz de tolerancia a fallas.
Volver a
las solicitudes AJAX y
HTTP .
¿Qué podría salir mal con AJAX?
Código de estado HTTP inesperado

El caso más simple será si el servidor devuelve el código de estado incorrecto que esperaba, digamos 500. Este es un escenario común, y probablemente tenga algunas herramientas para procesarlo. Por ejemplo, muestre al usuario una notificación "Se ha producido un error del servidor". Esto es claramente degradación, pero ¿qué tan elegante es? ¿Es posible aplicar una mejora progresiva aquí? No, definitivamente este no es el lugar para una mejora progresiva: la funcionalidad ya se ha degradado. Solo puedes superar este problema maravillosamente:
- Para descubrir que esta situación generalmente ocurrió en el cliente para evitarla en el futuro. Para esto, generalmente se utilizan registradores de errores, por ejemplo sentry.io .
- Caché los datos recibidos, si es posible. Genial si ya hubo una llamada a una solicitud similar y almacenó en caché los datos. En este caso, incluso si recibe un código de estado inesperado del servidor, puede mostrar la interfaz, aunque no con los datos más actuales.
- Intente volver a intentar la solicitud más tarde. Quizás este sea un bloqueo temporal del servidor y después de unos segundos se "lanzará". Puede realizar una segunda solicitud automáticamente o proporcionar esta opción al usuario.
- No bloquee el resto de la aplicación. Si muestra un spinner o un esqueleto antes de llamar a la solicitud HTTP, no olvide ocultarlo al completar la solicitud, exitosa o no. Esto puede parecer obvio, pero me he encontrado con bastante frecuencia.
- En general, puede haber muchos códigos de estado inesperados, por ejemplo, cuando una sesión de usuario expiró y el servidor respondió con el código 403. Para este error, se requiere un controlador separado que vuelva a emitir el token de sesión o envíe al usuario para autorización. La aplicación de conmutación por error debe tener controladores para todas las respuestas posibles del servidor.
Respuesta inválida

¡Nunca confíes en el backend! El servidor puede responder con el código 200, pero en el cuerpo de la respuesta devolverá los datos incorrectos que necesita. En esta situación, puede hacer lo mismo que con un código de estado inesperado, pero la dificultad radica en determinar que la respuesta es realmente inválida.
Si escribes en mecanografiado, entonces hay una herramienta genial:
typescript-json-schema . Con él, puede generar esquemas json desde interfaces mecanografiadas y usarlas para validar datos en tiempo de ejecución.
Respuesta larga

Este es el golpe que pocos esperan. Si recordamos errores o incluso datos de respuesta no válidos, raramente recordamos los tiempos de espera. El culpable puede ser no solo la aplicación del servidor, sino incluso el proveedor de Internet o el dispositivo del cliente.
No lo olvide, es mejor notificar al usuario que la solicitud es más larga de lo habitual que dejarlo cara a cara con un círculo giratorio en la pantalla. Cuando finaliza el tiempo asignado para la ejecución de la solicitud, puede pasar por un escenario similar al de las dos situaciones anteriores.
Falta de internet

Me impresionó mucho saber que Google Documents tiene un modo fuera de línea. Me ayudó mucho cuando decidí terminar de escribir un artículo en un avión donde no había internet.
Por supuesto, las aplicaciones son diferentes y muchas de ellas son prácticamente inútiles sin Internet. Pero incluso en estas aplicaciones, puede manejar el caso con la falta de conexión y mostrar un mensaje informativo (aunque también me gusta jugar al tiranosaurio en "Chrome").
Además, puede escuchar
eventos que conectan / desconectan la conexión a Internet . Y, por ejemplo, recargue automáticamente los datos durante el evento en línea en la ventana.
Interfaz tolerante a fallas: no es fácil
En total, la lista de acciones que deben implementarse al invocar la solicitud HTTP:
- Errores de registro
- Caché de datos y úsalo.
- Repetir solicitudes fallidas.
- No bloquee la interfaz.
- Manejar todas las respuestas posibles del servidor.
- Validar las respuestas del servidor.
- Establecer tiempos de espera.
- Modo sin conexión (falta de internet).
Lo que parecía trivial al principio se convirtió en una filosofía completa con muchos problemas. Por supuesto, esto no es un masthead. Pero si su aplicación ha alcanzado un alto nivel de madurez y desea crear una interfaz de muy alta calidad, entonces esta es la dirección en la que vale la pena desarrollarla.
El propósito de este artículo es hablar sobre posibles problemas al trabajar con solicitudes HTTP, pero no sobre soluciones específicas. Hoy en día, hay una gran cantidad de bibliotecas y marcos destinados a resolver estos problemas, por ejemplo, los interceptores HTTP en Angular.
Conociendo los posibles problemas, será mucho más fácil encontrar una solución para ellos en Internet.