Vue.js

Vuejs

Tutorial Vuejs: Solicitudes HTTP con Fetch API

Vuejs: Aprenda a usar la Fetch API para realizar solicitudes HTTP y gestionar respuestas de APIs de backend de forma eficiente en aplicaciones Vue.

Aprende Vuejs GRATIS y certifícate

¿Qué es la API Fetch?

La API Fetch es una interfaz de JavaScript que permite realizar solicitudes HTTP de manera sencilla y eficiente. Introducida como una mejora sobre el antiguo objeto XMLHttpRequest, la API Fetch utiliza promesas para manejar operaciones asíncronas, lo que facilita la gestión de respuestas y errores en las aplicaciones web modernas.

En el contexto de Vuejs, la API Fetch es invaluable para interactuar con APIs de backend desde los componentes de la aplicación. Al ser una API nativa del navegador, no requiere la instalación de bibliotecas adicionales, lo que simplifica el desarrollo y reduce la carga de dependencias.

La sintaxis básica de la API Fetch es simple y directa. Se utiliza la función global fetch() para realizar solicitudes, pasando como argumento la URL del recurso.

Una característica importante de la API Fetch es su capacidad para manejar diferentes métodos HTTP como GET, POST, PUT, PATCH y DELETE. Esto se logra pasando un segundo argumento a fetch(), un objeto de configuración donde se puede especificar el método, las cabeceras y el cuerpo de la solicitud.

Es esencial tener en cuenta que la API Fetch opera de forma asíncrona, lo que significa que las solicitudes no bloquean el hilo principal de ejecución. Esto mejora el rendimiento de la aplicación y proporciona una mejor experiencia al usuario.

Finalmente, es importante mencionar que, aunque la API Fetch es ampliamente soportada en navegadores modernos, siempre es recomendable verificar la compatibilidad con los navegadores que se espera que usen los usuarios de la aplicación. En casos donde se necesite soporte para navegadores más antiguos, se puede utilizar un polyfill para asegurar su funcionamiento.

Realizar una solicitud GET

Para interactuar con una API desde un componente de Vue, es común utilizar la API Fetch para realizar solicitudes HTTP GET y obtener datos del servidor. En Vue, puedes integrar Fetch dentro del ciclo de vida del componente para cargar datos cuando el componente se monta.

Por ejemplo, en el método mounted() del componente, podrías realizar una solicitud GET de la siguiente manera:

<template>
<img :src="perro" alt="">
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';

const perro = ref("")

onMounted(() => {
    fetch('https://dog.ceo/api/breeds/image/random')
        .then(response => response.json())
        .then((imagen: {message: string, status: string}) => {
            perro.value = imagen.message;
        })
        .catch(error => {
            console.error('Error al obtener el perro:', error);
        });
})
</script>

En este código, se hace una solicitud GET a la URL 'https://dog.ceo/api/breeds/image/random'. Al recibir la respuesta, se recibe una imagen aleatoria de un perro y se asigna a la propiedad perro del componente. Esto permite que los datos se reflejen automáticamente en la interfaz gracias a la reactividad de Vue.

Es importante manejar correctamente las promesas devueltas por fetch(). Utilizamos .then() para procesar la respuesta exitosa y .catch() para capturar cualquier error que pueda ocurrir durante la solicitud. Esto garantiza que la aplicación sea robusta y pueda manejar situaciones imprevistas.

Si necesitas incluir cabeceras específicas en tu solicitud, puedes pasar un objeto de configuración como segundo argumento de fetch(). Por ejemplo:

<template>
    <ul>
        <li v-for="product of products">
            <p>{{ product.title }}</p>
            <p>{{ product.description }}</p>
        </li>
    </ul>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';

const products = ref<{ title: string, description: string }[]>([])

onMounted(() => {
    fetch('https://fakestoreapi.com/products', {
        headers: {
            'Content-Type': 'application/json'
        }
    })
        .then(response => response.json())
        .then((datas) => {
            products.value = datas;
        })
        .catch(error => {
            console.error('Error al obtener el perro:', error);
        });
})
</script>

Aquí, se añaden cabeceras personalizadas como el tipo de contenido y la autenticación. Esto es útil cuando la API requiere ciertos encabezados para autorizar la solicitud o especificar el formato de los datos.

Para mejorar la legibilidad del código, puedes utilizar la sintaxis de async/await en lugar de promesas encadenadas. Esto se hace declarando el método mounted() como async y utilizando await para las operaciones asíncronas:

<template>
    <ul>
        <li v-for="product of products">
            <p>
                {{ product.title }}
            </p>
            <p>{{ product.description }}</p>
        </li>
    </ul>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';

const products = ref<{ title: string, description: string }[]>([])

onMounted(async () => {
    try {
        const response = await fetch('https://fakestoreapi.com/products');
        const datos = await response.json();
        products.value = datos;
    } catch (error) {
        console.error('Error al obtener los datos:', error);
    }
})
</script>

Con async/await, el código es más sencillo y se asemeja a código síncrono, lo que facilita su comprensión y mantenimiento. El bloque try...catch permite manejar excepciones de manera estructurada.

Es recomendable verificar el estado de la respuesta antes de procesarla. Puedes comprobar si response.ok es true para asegurarte de que la solicitud se realizó correctamente:

onMounted(async () => {
    try {
        const response = await fetch('https://fakestoreapi.com/products');
        if (!response.ok) {
            throw new Error(`Error en la solicitud: ${response.status}`);
        }
        const datos = await response.json();
        products.value = datos;
    } catch (error) {
        console.error('Error al obtener los datos:', error);
    }
})

Verificar response.ok es una buena práctica para manejar errores HTTP que pueden no generar una excepción pero indican que la solicitud no fue exitosa, como un 404 o 500.

Al asignar los datos obtenidos a una propiedad del componente, Vue se encarga de la reactividad, actualizando la interfaz de usuario automáticamente cuando cambian los datos. Esto simplifica la gestión del estado y asegura que la vista siempre refleje el estado actual de los datos.

Recuerda también considerar aspectos como el CORS (Cross-Origin Resource Sharing) si la API está en un dominio diferente, y asegurarte de que el servidor permite las solicitudes desde tu origen. Si es necesario, configura las cabeceras adecuadamente o ajusta la configuración del servidor.

Realizar una solicitud POST

Para enviar datos a un servidor desde un componente de Vue, es común utilizar solicitudes POST con la API Fetch. Este método permite transmitir información al backend, como formularios o datos para crear nuevos registros.

Un ejemplo básico de cómo realizar una solicitud POST es el siguiente:

export default {
    data() {
        return {
            title: "",
            price: 0,
            description: "",
            image: 'https://i.pravatar.cc',
            category: "",
            mensaje: ""
        };
    },
    methods: {
        async enviarDatos() {
            try {
                const respuesta = await fetch('https://fakestoreapi.com/products', {
                    method: "POST",
                    body: JSON.stringify(
                        {
                            title: this.title,
                            price: this.price,
                            description: this.description,
                            image: this.image,
                            category: this.category
                        }
                    )
                })

                if (!respuesta.ok) {
                    throw new Error(`Error en la solicitud: ${respuesta.status}`);
                }

                const datos = await respuesta.json();
                this.mensaje = 'Producto creado correctamente';
            } catch (error) {
                console.error('Error al enviar los datos:', error);
                this.mensaje = 'Hubo un problema al crear el producto';
            }
        }
    }
};

En este código, definimos un método enviarDatos que se encarga de realizar la solicitud POST. Es importante configurar correctamente las cabeceras y el cuerpo de la solicitud para asegurar que el servidor interprete los datos adecuadamente.

La propiedad headers incluye 'Content-Type': 'application/json', lo que indica que el cuerpo de la solicitud está en formato JSON. El cuerpo se construye utilizando JSON.stringify, convirtiendo el objeto JavaScript en una cadena JSON.

Utilizar async/await simplifica el manejo de operaciones asíncronas y hace que el código sea más legible. Además, con el bloque try...catch, podemos gestionar posibles errores que ocurran durante la solicitud, mejorando la robustez de la aplicación.

Al manejar la respuesta del servidor, es esencial verificar si la respuesta es exitosa antes de procesar los datos. Al comprobar respuesta.ok, nos aseguramos de que el servidor haya respondido con un código de estado en el rango 200-299. De lo contrario, lanzamos un error que es capturado en el bloque catch.

Para usar este método en la interfaz, podríamos tener un formulario donde los usuarios ingresen su nombre y edad:

<template>
    <div>
        <form @submit.prevent="enviarDatos">
            <input v-model="title" placeholder="Nombre del producto" required />
            <input v-model.number="price" type="number" placeholder="Precio" required />
            <input v-model="description" placeholder="Descripción del producto" required />
            <input v-model="category" placeholder="Categoría del producto" required />
            <button type="submit">Enviar</button>
        </form>
        <p>{{ mensaje }}</p>
    </div>
</template>

Aquí, utilizamos v-model para enlazar los campos del formulario con las propiedades title, price, description y category del componente. Al enviar el formulario, se ejecuta el método enviarDatos, que realiza la solicitud POST al servidor.

Es fundamental asegurarse de que los datos enviados cumplan con el formato y las validaciones necesarias. En este ejemplo, se utilizan los atributos required en los campos del formulario para validar la entrada del usuario antes de enviar los datos al servidor.

Si el servidor requiere autenticación o algún tipo de token, se deben incluir las cabeceras adicionales necesarias. Por ejemplo:

headers: {
  'Content-Type': 'application/json',
  'Authorization': `Bearer ${token}`
}

Donde token es una propiedad que contiene el token de acceso obtenido previamente. Añadir el encabezado Authorization es común cuando se trabaja con APIs que utilizan autenticación basada en tokens.

También es posible que el servidor devuelva datos relevantes en la respuesta después de crear el nuevo recurso. Por ejemplo, el identificador único del usuario creado. Podemos manejar esa información asignándola a una propiedad del componente:

const datos = await respuesta.json();
this.productId = datos.id;

Esto permite que la aplicación Vue reaccione a la nueva información y actualice la interfaz de usuario en consecuencia.

Cuando se trabaja con archivos u otras formas de datos, es posible que se necesite utilizar FormData en lugar de JSON. Por ejemplo, para subir una imagen junto con otros datos:

const formData = new FormData();
formData.append('nombre', this.nombre);
formData.append('imagen', this.imagenArchivo);

const respuesta = await fetch('https://api.ejemplo.com/usuarios', {
  method: 'POST',
  body: formData
});

En este caso, omitimos el encabezado 'Content-Type', ya que el navegador se encarga de establecerlo automáticamente cuando se utiliza FormData. Esto es esencial para el manejo correcto de archivos y datos mixtos.

Es importante tener en cuenta las consideraciones de seguridad al enviar datos sensibles. Asegurarse de utilizar HTTPS para cifrar la comunicación y proteger la información transmitida es una buena práctica estándar.

Además, al desarrollar aplicaciones internacionales, considerar la codificación y el manejo adecuado de caracteres especiales es crucial para evitar problemas de interpretación en el servidor.

Finalmente, mantener un manejo adecuado de promesas y operaciones asíncronas garantiza que la aplicación sea responsiva y proporcione una buena experiencia al usuario. Mostrar mensajes de éxito o error permite informar al usuario sobre el estado de la operación.

Realizar una solicitud PUT y PATCH

Las solicitudes PUT y PATCH se utilizan para actualizar datos existentes en un servidor a través de una API. En Vue, puedes implementar estas solicitudes utilizando la Fetch API, asegurándote de enviar los datos correctos y manejar adecuadamente las respuestas del servidor.

Para realizar una solicitud PUT, que suele utilizarse para reemplazar por completo un recurso, puedes hacer lo siguiente:

async function actualizarProducto() {
    try {
        const respuesta = await fetch(`https://fakestoreapi.com/products/${product.id}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(product)
        });

        if (!respuesta.ok) {
            throw new Error(`Error en la solicitud: ${respuesta.status}`);
        }

        await respuesta.json();

        mensaje.value = 'Producto actualizado correctamente';
    } catch (error) {
        console.error('Error al actualizar el producto:', error);
        mensaje.value = 'Hubo un problema al actualizar el producto';
    }
}

En este ejemplo, el método actualizarUsuario envía una solicitud PUT al servidor para actualizar la información de un usuario. Se utiliza el método HTTP PUT y se envían los datos del usuario en formato JSON mediante el uso de JSON.stringify.

Es importante incluir las cabeceras apropiadas, en este caso 'Content-Type': 'application/json', para que el servidor entienda el formato de los datos que está recibiendo.

Para una solicitud PATCH, que se utiliza para actualizar parcialmente un recurso, puedes modificar el método de la siguiente manera:

async actualizarParcialProducto() {
  try {
        const respuesta = await fetch(`https://fakestoreapi.com/products/${product.id}`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ price: product.price })
        });

        if (!respuesta.ok) {
            throw new Error(`Error en la solicitud: ${respuesta.status}`);
        }

        await respuesta.json();

        mensaje.value = 'Producto actualizado parcialmente';
    } catch (error) {
        console.error('Error al actualizar el producto:', error);
        mensaje.value = 'Hubo un problema al actualizar el producto';
    }
}

Aquí, el método actualizarParcialUsuario envía una solicitud PATCH, indicando que solo se va a modificar el campo edad del usuario. Nuevamente, es crucial configurar las cabeceras y el cuerpo de la solicitud adecuadamente.

Al realizar estas solicitudes, es buena práctica verificar el estado de la respuesta antes de procesar los datos. Comprobando respuesta.ok, nos aseguramos de que la operación fue exitosa antes de continuar.

En la interfaz de usuario, podrías tener un formulario para que el usuario edite sus datos:

<template>
    <h1>Producto: {{ product.title }}</h1>

    <div>
        <form @submit.prevent="actualizarProducto()">
            <input v-model="product.title" placeholder="Nombre del producto" required />
            <input v-model.number="product.price" type="number" placeholder="Precio" required />
            <input v-model="product.description" placeholder="Descripción del producto" required />
            <input v-model="product.category" placeholder="Categoría del producto" required />
            <button type="submit">Actualizar</button>
        </form>
        <p>{{ mensaje }}</p>
    </div>

</template>

Con v-model, los campos del formulario están enlazados a las propiedades de usuario, permitiendo una edición reactiva de los datos.

Si necesitas incluir autenticación en tus solicitudes, puedes añadir un token en las cabeceras. Por ejemplo:

headers: {
  'Content-Type': 'application/json',
  'Authorization': `Bearer ${this.token}`
}

Donde this.token es una propiedad que almacena el token de autenticación necesario para acceder a la API.

Además, considera manejar los posibles errores que puedan ocurrir durante la solicitud. Esto incluye errores de red o respuestas del servidor que indiquen un problema, como códigos de estado 4xx o 5xx. Proporcionar mensajes claros al usuario mejora la experiencia de uso de tu aplicación.

Al actualizar recursos en el servidor, es fundamental respetar la integridad de los datos. Asegúrate de enviar únicamente los campos que realmente necesiten ser actualizados. En el caso de PATCH, esto es especialmente relevante, ya que su propósito es modificar parcialmente un recurso sin afectar los demás campos.

Recuerda que la Fetch API devuelve una promesa que se resuelve con un objeto Response. Puedes utilizar los métodos disponibles en este objeto para procesar la respuesta, como response.json(), response.text(), etc.

Si prefieres usar async/await para un código más limpio y legible, como en los ejemplos anteriores, no olvides envolver las llamadas asíncronas en bloques try...catch para atrapar y manejar cualquier excepcionalidad.

Finalmente, al trabajar con APIs, es útil familiarizarse con las especificaciones de la API específica que estás utilizando. Diferentes APIs pueden tener requisitos particulares en cuanto al formato de los datos, las rutas de los endpoints o las necesidades de autenticación.

Realizar una solicitud DELETE

Las solicitudes DELETE se utilizan para eliminar recursos en un servidor a través de una API. En Vue, podemos implementar estas solicitudes utilizando la Fetch API, siguiendo prácticas recomendadas para asegurar una comunicación eficaz y segura con el backend.

Para eliminar un recurso específico, como un usuario identificado por su id, podemos crear un método dentro de nuestro componente que envíe una solicitud DELETE al endpoint correspondiente:

import { onMounted, ref } from 'vue';

const id = ref(0);
const mensaje = ref("");

const products = ref<{ id: number, title: string, price: number, description: string, image?: string, category?: string }[]>([]);

onMounted(async () => {
    try {
        const respuesta = await fetch('https://fakestoreapi.com/products');
        if (!respuesta.ok) {
            throw new Error(`Error al obtener los usuarios: ${respuesta.status}`);
        }
        const datos = await respuesta.json();
        console.log(datos);

        products.value = datos;
    } catch (error) {
        console.error('Error al cargar los usuarios:', error);
    }
})

async function eliminarProducto() {
    try {
        const respuesta = await fetch(`https://fakestoreapi.com/products/${id.value}`, {
            method: 'DELETE'
        });

        console.log(respuesta);


        if (!respuesta.ok) {
            throw new Error(`Error en la solicitud: ${respuesta.status}`);
        }

        products.value = products.value.filter(product => product.id !== id.value);
        mensaje.value = 'Producto eliminado correctamente';
    } catch (error) {
        console.error('Error al eliminar el producto:', error);
        mensaje.value = 'Hubo un problema al eliminar el producto';
    }
}

En este ejemplo, definimos el método eliminarUsuario, que acepta un id como parámetro. Utilizamos fetch para enviar una solicitud DELETE al endpoint correspondiente. Es importante verificar la respuesta del servidor, comprobando respuesta.ok, para asegurarnos de que la operación se realizó correctamente.

Tras una eliminación exitosa, actualizamos la lista de usuarios filtrando el que ha sido eliminado. Esto aprovecha la reactividad de Vue, asegurando que la interfaz de usuario se actualice automáticamente.

En la interfaz, podemos tener un listado de usuarios con un botón para eliminar cada uno:

<template>
    <input v-model="id" required>
    <button type="button" @click="eliminarProducto()">Eliminar</button>

    <ul>
        <li v-for="product of products">
            <p>{{ product.id }}</p>
            <p>{{ product.title }}</p>
        </li>
    </ul>
</template>

Aquí, utilizamos v-for para iterar sobre la lista de usuarios y v-on (shorthand @) para manejar el evento de clic en el botón de eliminar. La función eliminarUsuario se invoca con el id del usuario seleccionado.

Si la API requiere autenticación o necesita ciertas cabeceras, podemos incluirlas en la solicitud:

const respuesta = await fetch(`https://api.ejemplo.com/usuarios/${id}`, {
  method: 'DELETE',
  headers: {
    'Authorization': `Bearer ${this.token}`
  }
});

Donde this.token es una propiedad que almacena el token de acceso. Es esencial incluir las cabeceras adecuadas para que el servidor pueda autorizar la operación.

En ocasiones, el servidor puede esperar un cuerpo en la solicitud DELETE, aunque esto no es común. Si fuera necesario, podemos incluir un cuerpo utilizando la propiedad body en la configuración:

const respuesta = await fetch(`https://api.ejemplo.com/recursos/${id}`, {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ motivo: 'Duplicado' })
});

Es crucial respetar las especificaciones de la API que estemos utilizando, ya que puede variar según el diseño del backend.

Al manejar errores, proporcionamos información útil tanto para los desarrolladores como para los usuarios. Utilizar un bloque try...catch nos permite capturar excepciones y manejar situaciones como problemas de red o respuestas con códigos de error.

Además, es buena práctica evitar acciones inseguras sin confirmación del usuario. Podemos implementar una confirmación antes de proceder con la eliminación:

async confirmarYEliminar(id) {
  if (confirm('¿Estás seguro de que deseas eliminar este usuario?')) {
    await this.eliminarUsuario(id);
  }
}

Cambiando el manejador de evento en el botón a @click="confirmarYEliminar(usuario.id)", añadimos una capa de seguridad para prevenir eliminaciones accidentales.

Por último, asegúrate de considerar las implicaciones de CORS (Cross-Origin Resource Sharing) si el frontend y el backend están en orígenes diferentes. El servidor debe estar configurado para permitir solicitudes desde tu dominio, incluyendo el método DELETE en las políticas de acceso.

Manejo de errores con API Fetch

Al utilizar la API Fetch en aplicaciones de Vue para realizar solicitudes HTTP, es fundamental implementar un adecuado manejo de errores para garantizar la robustez de la aplicación y ofrecer una buena experiencia al usuario. Los errores pueden ocurrir por diversas razones, como problemas de red, respuestas no exitosas del servidor o fallos en el procesamiento de los datos recibidos.

La detección de errores de red se puede realizar utilizando bloques try...catch en combinación con la sintaxis async/await. Los errores de red, como la falta de conectividad o tiempos de espera, generan excepciones que pueden ser capturadas en el bloque catch y manejadas apropiadamente.

async function obtenerDatos() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/datos');
    // Procesar la respuesta
  } catch (error) {
    console.error('Error de red:', error);
    // Mostrar mensaje al usuario
  }
}

En este ejemplo, si ocurre un error de red, el bloque catch captura la excepción, permitiendo informar al usuario y tomar acciones necesarias.

Además de los errores de red, es importante manejar las respuestas HTTP no exitosas. La API Fetch no lanza excepciones para códigos de estado HTTP como 404 o 500. Por ello, es necesario verificar manualmente el estado de la respuesta utilizando la propiedad response.ok o response.status.

async function obtenerUsuarios() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/usuarios');
    if (!respuesta.ok) {
      throw new Error(`Error HTTP: ${respuesta.status}`);
    }
    const datos = await respuesta.json();
    // Procesar los datos
  } catch (error) {
    console.error('Error al obtener usuarios:', error);
    // Mostrar mensaje al usuario
  }
}

Aquí, si la respuesta del servidor no es exitosa, se lanza un error que es capturado en el bloque catch. Esto permite un manejo unificado de errores de red y errores de respuesta.

Para proporcionar una mejor experiencia de usuario, es recomendable mostrar mensajes claros y útiles cuando ocurren errores. Puedes actualizar el estado del componente para indicar que hubo un problema, y así la interfaz reflejará la situación actual.

export default {
  data() {
    return {
      usuarios: [],
      error: null,
      cargando: false
    };
  },
  methods: {
    async cargarUsuarios() {
      this.cargando = true;
      this.error = null;
      try {
        const respuesta = await fetch('https://api.ejemplo.com/usuarios');
        if (!respuesta.ok) {
          throw new Error(`Error HTTP: ${respuesta.status}`);
        }
        const datos = await respuesta.json();
        this.usuarios = datos;
      } catch (error) {
        this.error = 'No se pudieron cargar los usuarios. Por favor, inténtelo más tarde.';
        console.error('Error al cargar los usuarios:', error);
      } finally {
        this.cargando = false;
      }
    }
  },
  mounted() {
    this.cargarUsuarios();
  }
};

En este código, se gestionan tres estados: cargando, error y éxito. Esto permite a la interfaz mostrar indicaciones visuales, como un indicador de carga o mensajes de error, mejorando la interacción con el usuario.

Es posible que necesites manejar errores específicos según el código de estado HTTP. Por ejemplo, puedes realizar acciones diferentes si el servidor responde con un 401 (No autorizado) o un 404 (No encontrado).

if (respuesta.status === 404) {
  this.error = 'El recurso solicitado no existe.';
} else if (respuesta.status === 401) {
  this.error = 'No está autorizado para acceder a este recurso.';
} else {
  throw new Error(`Error HTTP: ${respuesta.status}`);
}

De esta forma, ofrecemos mensajes más detallados y acciones específicas para cada situación.

Para un manejo más avanzado, puedes crear una función de ayuda para gestionar las respuestas, centralizando el manejo de errores.

async function manejarRespuesta(respuesta) {
  if (respuesta.ok) {
    return respuesta.json();
  } else {
    const mensajeError = await respuesta.text();
    throw new Error(mensajeError || `Error HTTP: ${respuesta.status}`);
  }
}

async function obtenerDatos() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/datos');
    const datos = await manejarRespuesta(respuesta);
    // Procesar los datos
  } catch (error) {
    console.error('Error al obtener datos:', error);
    // Manejo de error
  }
}

Esta estrategia facilita la reutilización del código y asegura un manejo consistente de las respuestas en toda la aplicación.

También es importante considerar el manejo de tiempo de espera en las solicitudes. La API Fetch no tiene soporte nativo para configurar un timeout, pero puedes implementarlo utilizando Promise.race para competir entre la solicitud y una promesa que rechaza después de cierto tiempo.

function tiempoEspera(ms) {
  return new Promise((_, reject) => setTimeout(() => reject(new Error('Tiempo de espera agotado')), ms));
}

async function obtenerDatosConTimeout() {
  try {
    const respuesta = await Promise.race([
      fetch('https://api.ejemplo.com/datos'),
      tiempoEspera(5000) // 5 segundos de tiempo de espera
    ]);
    if (!respuesta.ok) {
      throw new Error(`Error HTTP: ${respuesta.status}`);
    }
    const datos = await respuesta.json();
    // Procesar los datos
  } catch (error) {
    console.error('Error al obtener datos:', error);
    // Manejo de error
  }
}

Así, si la respuesta tarda más de 5 segundos, se lanza un error de tiempo de espera, permitiendo manejar este caso en el bloque catch.

En entornos donde se requiere soportar cancelación de solicitudes, puedes utilizar el AbortController disponible en la API Fetch. Esto permite cancelar una solicitud en curso si no es necesaria, liberando recursos.

const controlador = new AbortController();
const señal = controlador.signal;

async function obtenerDatos() {
  try {
    const respuesta = await fetch('https://api.ejemplo.com/datos', { signal: señal });
    if (!respuesta.ok) {
      throw new Error(`Error HTTP: ${respuesta.status}`);
    }
    const datos = await respuesta.json();
    // Procesar los datos
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Solicitud cancelada');
    } else {
      console.error('Error al obtener datos:', error);
    }
  }
}

// Cancelar la solicitud después de 3 segundos
setTimeout(() => controlador.abort(), 3000);

Con AbortController, puedes cancelar solicitudes pendientes y capturar el error específico de cancelación para distinguirlo de otros errores.

Finalmente, es esencial asegurarse de que la aplicación maneja correctamente los errores de análisis de datos, como al convertir una respuesta en JSON. Si la respuesta no es un JSON válido, se generará un error que debe ser capturado.

try {
  const datos = await respuesta.json();
} catch (error) {
  throw new Error('Error al analizar la respuesta JSON');
}

Al manejar de forma integral los diferentes tipos de errores, tu aplicación será más sólida y ofrecerá una mejor experiencia al usuario.

Aprende Vuejs GRATIS online

Ejercicios de esta lección Solicitudes HTTP con Fetch API

Evalúa tus conocimientos de esta lección Solicitudes HTTP con Fetch API con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de Vuejs

Accede a todas las lecciones de Vuejs y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Vue Y Su Ecosistema

Vue.js

Introducción Y Entorno

Instalar Y Configurar Vue Con Vite

Vue.js

Introducción Y Entorno

Introducción A La Sintaxis De Plantillas

Vue.js

Componentes

Introducción A Componentes

Vue.js

Componentes

Componentes Con Options Api

Vue.js

Componentes

Componentes Con Composition Api

Vue.js

Componentes

Renderizado Condicional Con V-if

Vue.js

Componentes

Renderizado Iterativo Con V-for

Vue.js

Componentes

Props Y Comunicación Entre Componentes

Vue.js

Componentes

Manejo De Eventos En Vue Con V-on

Vue.js

Componentes

Binding Bidireccional Con V-model Y Definemodel

Vue.js

Componentes

Estilización De Componentes

Vue.js

Componentes

Reactividad Con Ref Y Reactive

Vue.js

Composición Y Reactividad

Ciclo De Vida Con Composition Api

Vue.js

Composición Y Reactividad

Composition Api: Provide E Inject

Vue.js

Composición Y Reactividad

Introducción A Los Composables

Vue.js

Composición Y Reactividad

Uso Avanzado De Composables

Vue.js

Composición Y Reactividad

Introducción A Vue Router

Vue.js

Navegación Y Enrutamiento

Definición Y Manejo De Rutas

Vue.js

Navegación Y Enrutamiento

Rutas Anidadas Y Dinámicas

Vue.js

Navegación Y Enrutamiento

Navegación Programática Y Redirección

Vue.js

Navegación Y Enrutamiento

Solicitudes Http Con Fetch Api

Vue.js

Interacción Http Con Apis De Backend

Solicitudes Http Con Axios

Vue.js

Interacción Http Con Apis De Backend

Introducción A Suspense

Vue.js

Interacción Http Con Apis De Backend

Evaluación Test De Conocimientos Vuejs

Vue.js

Evaluación

Accede GRATIS a Vuejs y certifícate

Certificados de superación de Vuejs

Supera todos los ejercicios de programación del curso de Vuejs y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender la funcionalidad básica de la Fetch API y su integración con Vue.
  2. Realizar solicitudes HTTP utilizando métodos como GET, POST, PUT, PATCH y DELETE.
  3. Manejar respuestas y errores de forma asíncrona con promesas y async/await.
  4. Configurar cabeceras HTTP y manejar la autenticación con tokens.
  5. Implementar prácticas de manejo de errores con la API Fetch.