En este artículo, se muestran algunos enfoques de control de errores cuando se trabaja con la API de Fetch. La API de Fetch te permite realizar una solicitud a un recurso de red remoto. Cuando haces una llamada de red remota, tu página web queda sujeta a una variedad de posibles errores de red.
En las siguientes secciones, se describen posibles errores y cómo escribir código que proporcione un nivel razonable de funcionalidad que sea resistente a errores y condiciones de red inesperadas. Un código resiliente mantiene satisfechos a tus usuarios y mantiene un nivel de servicio estándar para tu sitio web.
Anticípate a posibles errores de red
En esta sección, se describe una situación en la que el usuario crea un video nuevo llamado "My Travels.mp4"
y, luego, intenta subirlo a un sitio web para compartir videos.
Cuando se trabaja con la función Fetch, es fácil considerar el camino ideal en el que el usuario sube correctamente el video. Sin embargo, hay otras rutas que no son tan sencillas, pero para las que los desarrolladores web deben planificar. Estas rutas (infelices) pueden ocurrir debido a un error del usuario, a condiciones ambientales inesperadas o debido a un error en el sitio web para compartir videos.
Ejemplos de errores del usuario
- El usuario sube un archivo de imagen (como JPEG) en lugar de un archivo de video.
- El usuario comienza a subir el archivo de video incorrecto. Después de completar la carga, el usuario especifica el archivo de video correcto que debe subir.
- El usuario hace clic accidentalmente en "Cancelar carga" mientras se sube el video.
Ejemplos de cambios ambientales
- La conexión a Internet se desconecta mientras se sube el video.
- El navegador se reinicia mientras se sube el video.
- Los servidores del sitio web de uso compartido de videos se reinician mientras se sube el video.
Ejemplos de errores con el sitio web de uso compartido de videos
- El sitio web para compartir videos no puede admitir un nombre de archivo con un espacio. En lugar de
"My Travels.mp4"
, espera un nombre como"My_Travels.mp4"
o"MyTravels.mp4"
. - El sitio web para compartir videos no puede subir un video que supere el tamaño máximo de archivo aceptable.
- El sitio web para compartir videos no admite el códec de video del video subido.
Estos ejemplos pueden ocurrir y, de hecho, ocurren en el mundo real. Es posible que hayas encontrado ejemplos de este tipo en el pasado. Elige un ejemplo de cada una de las categorías anteriores y analiza los siguientes puntos:
- ¿Cuál es el comportamiento predeterminado si el servicio de uso compartido de videos no puede controlar el ejemplo dado?
- ¿Qué espera que suceda el usuario en el ejemplo?
- ¿Cómo podemos mejorar el proceso?
Controla los errores con la API de Fetch
Ten en cuenta que los siguientes ejemplos de código usan await
de nivel superior (compatibilidad con navegadores) porque esta función puede simplificar tu código.
Cuando la API de Fetch genera errores
En este ejemplo, se usa una sentencia bloque try
/catch
para detectar cualquier error que se genere dentro del bloque try
. Por ejemplo, si la API de Fetch no puede recuperar el recurso especificado, se genera un error. Dentro de un bloque catch
como este, asegúrate de proporcionar una experiencia del usuario significativa. Si se le muestra al usuario un ícono giratorio, una interfaz de usuario común que representa algún tipo de progreso, puedes realizar las siguientes acciones dentro de un bloque catch
:
- Quita el ícono giratorio de la página.
- Proporciona mensajes útiles que expliquen qué salió mal y qué opciones puede tomar el usuario.
- Según las opciones disponibles, presenta al usuario un botón "Reintentar".
- En segundo plano, envía los detalles del error a tu servicio de seguimiento de errores o al backend. Esta acción registra el error para que se pueda diagnosticar en una etapa posterior.
try {
const response = await fetch('https://website');
} catch (error) {
// TypeError: Failed to fetch
console.log('There was an error', error);
}
En una etapa posterior, mientras diagnosticas el error que registraste, puedes escribir un caso de prueba para detectarlo antes de que los usuarios sepan que algo está mal. Según el error, la prueba puede ser una prueba de unidad, integración o aceptación.
Cuando el código de estado de la red representa un error
En este ejemplo de código, se realiza una solicitud a un servicio de prueba HTTP que siempre responde con el código de estado HTTP 429 Too Many Requests
. Curiosamente, la respuesta no llega al bloque catch
. Un estado 404, entre otros códigos de estado, no muestra un error de red, sino que se resuelve de forma normal.
Para verificar que el código de estado HTTP se haya ejecutado correctamente, puedes usar cualquiera de las siguientes opciones:
- Usa la propiedad
Response.ok
para determinar si el código de estado estaba en el rango de200
a299
. - Usa la propiedad
Response.status
para determinar si la respuesta se realizó correctamente. - Usa cualquier otro metadato, como
Response.headers
, para evaluar si la respuesta fue exitosa.
let response;
try {
response = await fetch('https://httpbin.org/status/429');
} catch (error) {
console.log('There was an error', error);
}
// Uses the 'optional chaining' operator
if (response?.ok) {
console.log('Use the response here!');
} else {
console.log(`HTTP Response Code: ${response?.status}`)
}
La práctica recomendada es trabajar con las personas de tu organización y equipo para comprender los posibles códigos de estado de respuesta HTTP. A veces, los desarrolladores de backend, los ingenieros de servicio y las operaciones de desarrolladores pueden proporcionar información única sobre posibles casos extremos que tal vez no preveas.
Cuando se produce un error al analizar la respuesta de la red
En este ejemplo de código, se muestra otro tipo de error que puede surgir cuando se analiza un cuerpo de respuesta. La interfaz Response
ofrece métodos convenientes para analizar diferentes tipos de datos, como texto o JSON. En el siguiente código, se realiza una solicitud de red a un servicio de prueba HTTP que muestra una cadena HTML como cuerpo de la respuesta. Sin embargo, se intenta analizar el cuerpo de la respuesta como JSON, lo que genera un error.
let json;
try {
const response = await fetch('https://httpbin.org/html');
json = await response.json();
} catch (error) {
if (error instanceof SyntaxError) {
// Unexpected token < in JSON
console.log('There was a SyntaxError', error);
} else {
console.log('There was an error', error);
}
}
if (json) {
console.log('Use the JSON here!', json);
}
Debes preparar tu código para que tome una variedad de formatos de respuesta y verificar que una respuesta inesperada no dañe la página web para el usuario.
Considera la siguiente situación: tienes un recurso remoto que muestra una respuesta JSON válida y se analiza correctamente con el método Response.json()
. Puede suceder que el servicio falle. Una vez que se descarga, se muestra una 500 Internal Server Error
. Si no se usan las técnicas de manejo de errores adecuadas durante el análisis de JSON, es posible que se dañe la página para el usuario porque se genera un error no controlado.
Cuándo se debe cancelar la solicitud de red antes de que se complete
En este ejemplo de código, se usa un AbortController
para cancelar una solicitud en curso. Una solicitud en curso es una solicitud de red que se inició, pero que no se completó.
Las situaciones en las que es posible que debas cancelar una solicitud en curso pueden variar, pero, en última instancia, depende de tu caso de uso y entorno. En el siguiente código, se muestra cómo pasar un AbortSignal
a la API de Fetch. El AbortSignal
está conectado a un AbortController
, y el AbortController
incluye un método abort()
, que le indica al navegador que se debe cancelar la solicitud de red.
const controller = new AbortController();
const signal = controller.signal;
// Cancel the fetch request in 500ms
setTimeout(() => controller.abort(), 500);
try {
const url = 'https://httpbin.org/delay/1';
const response = await fetch(url, { signal });
console.log(response);
} catch (error) {
// DOMException: The user aborted a request.
console.log('Error: ', error)
}
Conclusión
Un aspecto importante de la administración de errores es definir las diferentes partes que pueden fallar. Para cada situación, asegúrate de tener un resguardo adecuado para el usuario. En relación con una solicitud de recuperación, hazte preguntas como las siguientes:
- ¿Qué sucede si se cae el servidor de destino?
- ¿Qué sucede si Fetch recibe una respuesta inesperada?
- ¿Qué sucede si falla la conexión a Internet del usuario?
Según la complejidad de tu página web, también puedes esbozar un diagrama de flujo que describa la funcionalidad y la interfaz de usuario para diferentes situaciones.