Skip to content

Cómo Abortar Solicitudes API y Manejar Errores en Vue.js con VueUse

Introducción

Cuando se trabaja con operaciones asíncronas en aplicaciones Vue, es crucial gestionar las solicitudes de manera eficiente, especialmente cuando se trata de solicitudes potencialmente largas o innecesarias. En este artículo, exploraremos cómo abortar solicitudes utilizando VueUse y manejar los errores lanzados por estas solicitudes abortadas.

Problema

En las aplicaciones web modernas, es común realizar múltiples llamadas API para obtener datos. Sin embargo, hay escenarios en los que podríamos querer cancelar solicitudes en curso, como cuando un usuario navega fuera de una página o cuando una nueva solicitud reemplaza a una existente. Además, necesitamos manejar los errores que pueden ocurrir al abortar estas solicitudes para garantizar una experiencia de usuario fluida.

Contexto

VueUse proporciona un potente composable useFetch que nos permite realizar solicitudes HTTP con funcionalidad de aborto incorporada. Veamos cómo podemos aprovechar esta característica:

typescript
const { abort, canAbort } = useFetch(url);

setTimeout(() => {
  if (canAbort.value) abort();
}, 100);

En este ejemplo, podemos abortar una solicitud utilizando la función abort proporcionada por useFetch. La propiedad canAbort indica si la solicitud puede ser abortada.

También podemos establecer un tiempo de espera automático para abortar solicitudes:

typescript
const { data } = useFetch(url, { timeout: 100 });

Esto abortará automáticamente la solicitud después de 100 milisegundos.

Solución

Ahora, implementemos una solución que demuestre cómo abortar solicitudes y manejar errores en un componente Vue. Crearemos un componente que obtiene mensajes y permite al usuario cancelar la solicitud haciendo clic en un botón varias veces.

vue
<template>
  <div>
    <button @click="getMessages">Obtener Mensajes</button>
    <div v-if="loading">Cargando...</div>

    <ul v-else>
      <li v-for="message in messages" :key="message.id">
        {{ message.text }}
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { useFetch } from '@vueuse/core';
import { defineStore } from 'pinia';

interface Message {
  id: number;
  text: string;
}

const useStore = defineStore('main', {
  state: () => ({
    cancellableRequests: new Map<string, { abort: () => void }>(),
  }),
});

const store = useStore();

const messages = ref<Message[]>([]);
const loading = ref(false);

const getMessages = async (): Message[] => {
  try {
    loading.value = true;

    const url = '/api/messages';
    const token = 'getMessages';

    if (store.cancellableRequests.has(token)) {
      store.cancellableRequests.get(token)?.abort();
      store.cancellableRequests.delete(token);
    }

    const { execute, abort, data, error } = useFetch(url, {
      immediate: false,
    })
      .get()
      .json<{ messages: Message[] }>();

    store.cancellableRequests.set(token, { abort });

    await execute();

    if (error.value) {
      if error.value instanceof Error && error.value.name === 'AbortError') {
        store.cancellableRquests.delete(token);
        return []
      }

      throw new Error('Algo salió mal. Inténtelo de nuevo más tarde.')
    }

    return data.value.messages;
  } finally {
    loading.value = false;
  }
};
</script>

En este ejemplo, hemos creado un componente Vue que demuestra cómo abortar solicitudes y manejar errores:

  1. Definimos un store Pinia para gestionar las solicitudes cancelables.
  2. La función getMessages es responsable de obtener mensajes y manejar el ciclo de vida de la solicitud.
  3. Antes de realizar una nueva solicitud, verificamos si existe una solicitud existente con el mismo token y la abortamos si existe.
  4. Utilizamos useFetch de VueUse para realizar la llamada API.
  5. Almacenamos la función abort en nuestro store Pinia, lo que nos permite cancelar la solicitud más tarde si es necesario.
  6. Manejamos errores, incluyendo el AbortError, que se lanza cuando se cancela una solicitud.
  7. Devolvemos los mensajes obtenidos si tiene éxito, o un array vacío si la solicitud fue abortada.
  8. Finalmente, limpiamos eliminando la solicitud de nuestro store y estableciendo el estado de carga en falso.

Esta implementación permite una gestión eficiente de las llamadas API, evitando solicitudes de red innecesarias y mejorando la experiencia general del usuario.

Conclusión

Al implementar esta solución, hemos abordado con éxito la pregunta inicial de cómo abortar solicitudes utilizando VueUse y manejar los errores lanzados por ellas. Este enfoque permite una gestión eficiente de las llamadas API, evitando solicitudes de red innecesarias y mejorando la experiencia general del usuario.