Por qué los desarrolladores de JavaScript deberían preferir Axios a Fetch

by Janeth Kent Date: 01-03-2021 javascript ajax fetch json axios


Por qué los desarrolladores de JavaScript deberían preferir Axios a Fetch

En mi artículo anterior, "Usando la Api Fetch Para Hacer Llamadas Ajax", hablé de los fundamentos de la API Fetch. Pero vale la pena reconocer que fetch() no es siempre una solución ideal, y a veces hay mejores alternativas para hacer peticiones HTTP. Aquí vamos a examinar por qué Axios es mejor que fetch() en el desarrollo.

Visión general y sintaxis

Visión general y sintaxis en Fetch

fetch() forma parte de un método window-object de JavaScript dentro de la Fetch API. Está incorporado, por lo que los usuarios no tienen que instalarlo. fetch() nos permite obtener datos de la API de forma asíncrona sin necesidad de instalar ninguna librería adicional.

  
  fetch(url)
  .then((res) => {
    // maneja la respuesta
  })
  .catch((error) => {
    // maneja el error
  });
  

El fragmento de código anterior es una simple solicitud de obtención fetch(). En el método fetch(), hay un argumento obligatorio, que es url. url es una ruta de la que el usuario desea obtener datos. Entonces el método fetch() devuelve una promesa que puede resolver el objeto de respuesta o rechazarlo con un error.

fetch(url, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
})
  .then((response) => response.json())
  .catch((error) => console.log(error));

Los segundos argumentos del método fetch() son opciones, y son opcionales. Si el usuario no pasa las opciones, la petición siempre obtiene, y descarga el contenido de la URL dada. Como mencioné antes, la promesa devuelve el objeto de respuesta, y debido a eso, los usuarios necesitan usar otro método para obtener el cuerpo de la respuesta. Hay algunos métodos diferentes que los usuarios pueden utilizar dependiendo del formato del cuerpo.

  • response.json()
  • response.text()
  • response.blob()
  • response.formData()
  • response.arrayBuffer()

El más popular es response.json().

Desafortunadamente, la función fetch() incorporada no está en Node.js, pero hay un polyfill como node-fetch. Entre node-fetch y la función fetch() del navegador, existen varias variaciones conocidas.

Visión general y sintaxis en Axios

Axios es una librería JavaScript para realizar peticiones HTTP desde Node o XMLHttpRequest o un navegador. Como biblioteca moderna, está basada en la API Promise. Axios tiene algunas ventajas, como la protección contra los ataques de falsificación de solicitudes entre sitios (CSFR). Para poder usar la librería Axios, los usuarios tienen que instalarla e importarla a su proyecto, usando CDN, npm, Yarn, o Bower.

axios.get(url)
  .then((response) => console.log(response))
  .catch((error) => console.log(error));

El fragmento de código anterior es un método get y un simple callback para una respuesta y un error. Cuando los usuarios crean un objeto de configuración, pueden definir un montón de propiedades. Las más comunes son url, baseURL, params, auth, headers, responseType, y data.

Como respuesta, Axios devuelve una promesa que se resolverá con el objeto respuesta o con un objeto error. En el objeto de respuesta, existen los siguientes valores:

  • data:Cuerpo real de la respuesta
  • status: Código de estado HTTP de la llamada, como 200 o 404
  • statusText: Estado HTTP en forma de mensaje de texto
  • headers: Lo mismo que en la request
  • config: configuración Request
  • request: objecto XMLHttpRequest (XHR)
axios({
  url: "http://api.com",
  method: "POST",
  header: {
    "Content-Type": "application/json",
  },
  data: { name: "Holyguard", age: 45 },
});

Los usuarios necesitan trabajar con dos promesas en fetch(). Los usuarios pueden evitar la repetición de tareas y escribir un código más limpio y sucinto en Axios.
Axios utiliza la propiedad data, pero fetch() utiliza la propiedad body para tratar los datos. En fetch(), la URL se pasa como argumento, pero en Axios la URL se establece en el objeto config.

JSON

JSON con Fetch

Usando el método fetch(), los usuarios necesitan usar algún tipo de método en los datos de la respuesta. Cuando los usuarios están enviando el cuerpo con la solicitud, los usuarios necesitan stringificar los datos.

fetch('url')
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.log(error));

En el trozo de código anterior, con la respuesta, los usuarios necesitan procesar la acción response.json(). Cuando se trata de los datos JSON en fetch(), hay un proceso de dos pasos. Los usuarios necesitan hacer la solicitud real primero y luego llamar al método .json() en la respuesta.

JSON con Axios

En Axios los usuarios pasan datos en la solicitud u obtienen datos de la respuesta, y los datos se encadenan automáticamente. Por lo tanto, no se requieren otras operaciones.

axios.get('url')
    .then((response)=>console.log(response))
    .catch((error)=>console.log(error))

En el ejemplo anterior, puedes ver que sólo necesitas un then.
La transformación automática de los datos es una buena característica para tener en Axios.

Tratamiento de errores

Tratamiento de errores en Fetch

Cada vez que se obtiene una respuesta del método fetch(), es necesario comprobar si el estado es un éxito porque incluso si no lo es, se obtendrá la respuesta. En el caso de fetch(), una promesa no se resolverá si y sólo si la petición no se completa.

fetch('url')
    .then((response)=>{
        if(!response.ok){
            throw Error (response.statusText);
        }
        return response.json();
    })
    .then((data)=>console.log(data))
    .catch((error)=>console.log(error))

Fetch() no lanza errores de red. Por lo tanto, siempre debe comprobar la propiedad response.ok cuando trabaje con fetch(). Podrías extraer esta comprobación de errores en una función para hacerla más fácil y reutilizable.

const checkError = response => {
    if (!response.ok) throw Error(response.statusText);
    return response.json();
  };
  
  fetch("url")
    .then(checkError)
    .then(data => console.log(data))
    .catch(error => console.log("error", error));

Tratamiento de errores en Axios

En Axios, el manejo de errores es bastante fácil porque Axios arroja errores de red. Si hay una mala respuesta como 404, la promesa será rechazada y devolverá un error. Por lo tanto, necesitas atrapar un error, y puedes comprobar qué tipo de error fue.

axios.get('url')
    .then((response)=> console.log(response))
    .catch((error)=>{
        if(error.response){
        // Cuando el código de estado de la respuesta está fuera del rango 2xxx 
        console.log(error.response.data);
        console.log(error.response.status);
        console.log(error.response.headers);
        } else if (error.request){
            // Cuando no se ha recibido ninguan respuesta despues de haber enviado la request 
            console.log(error.request);
        } else {
            // Error
            console.log(error.message);
        }
    })

Progreso de la descarga

Cuando se cargan activos de gran tamaño, los indicadores de progreso son muy útiles para los usuarios con una velocidad de Internet lenta. En los indicadores de progreso implementados anteriormente, los desarrolladores utilizaban XMLHttpRequest.onprogress como controlador de devolución de llamada.

Progreso de la descarga en Fetch

Para seguir el progreso de la descarga en fetch(), puedes utilizar una de las propiedades de response.body, un objeto ReadableStream. Éste proporciona los datos del cuerpo trozo a trozo, y permite contar cuántos datos se consumen en el tiempo.

// código original: https://github.com/AnthumChris/fetch-progress-indicators
const element = document.getElementById('progress');

fetch('url')
  .then(response => {

    if (!response.ok) {
      throw Error(response.status+' '+response.statusText)
    }

    // asegurate que ReadableStream esté suportado
    if (!response.body) {
      throw Error('ReadableStream no suportado en este navegador.')
    }

    // almacenar el tamaño del entity-body, en bytes
    const contentLength = response.headers.get('content-length');

    // asegurate que contentLength esté disponible
    if (!contentLength) {
      throw Error('Content-Length encabezado de respuesta no disponible');
    }

    // convertir el entero en un número de base-10
    const total = parseInt(contentLength, 10);

    let loaded = 0;

    return new Response(

      // crear y devolver un flujo legible
      new ReadableStream({
        start(controller) {
          const reader = response.body.getReader();

          read();
          function read() {
            reader.read().then(({done, value}) => {
              if (done) {
                controller.close();
                return; 
              }
              loaded += value.byteLength;
              progress({loaded, total})
              controller.enqueue(value);
              read();
            }).catch(error => {
              console.error(error);
              controller.error(error)                  
            })
          }
        }
      })
    );
  })
  .then(response => 
    // construir un blob a partir de los datos
    response.blob()
  )
  .then(data => {
    // insertar la imagen descargada en la página
    document.getElementById('img').src = URL.createObjectURL(data);
  })
  .catch(error => {
    console.error(error);
  })

function progress({loaded, total}) {
  element.innerHTML = Math.round(loaded/total*100)+'%';
}

El ejemplo anterior demuestra el uso de ReadableStream para proporcionar a los usuarios información instantánea mientras se descargan las imágenes.

Progreso de la descarga en Axios

En Axios, implementar un indicador de progreso también es posible, y es aún más fácil porque existe un módulo listo que puede ser instalado e implementado. Se llama Axios Progress Bar.

loadProgressBar();

function downloadFile(url) {
    axios.get(url, {responseType: 'blob'})
      .then(response => {
        const reader = new window.FileReader();
        reader.readAsDataURL(response.data); 
        reader.onload = () => {
          document.getElementById('img').setAttribute('src', reader.result);
        }
      })
      .catch(error => {
        console.log(error)
      });
}

Progreso de Upload

Progreso de Upload en Fetch

En fetch(), no se puede controlar el progreso de las subidas.

Progreso de Upload en Axios

En Axios, puedes monitorizar el progreso de tus subidas. Esto podría ser un punto de inflexión si estás desarrollando una aplicación para subir videos o fotos.

const config = {
    onUploadProgress: event => console.log(event.loaded)
  };

axios.put("/api", data, config);

 

Interceptación HTTP

La interceptación puede ser importante para ti cuando necesites comprobar o cambiar tu petición HTTP desde la aplicación al servidor o al revés - por ejemplo, autenticación, registro, etc.

Interceptación HTTP en Fetch

Fetch() no proporciona la interceptación HTTP por defecto. Existe la posibilidad de sobrescribir el método fetch() y definir lo que debe ocurrir durante el envío de la petición, pero requerirá más código y puede ser más complicado que utilizar las funcionalidades de Axios. Puedes sobrescribir el método fetch() global y definir tu propio interceptor, como el siguiente código:

fetch = (originalFetch => {
    return (...arguments) => {
      const result = originalFetch.apply(this, arguments);
        return result.then(console.log('Request was sent'));
    };
  })(fetch);
  
fetch('url')
    .then(response => response.json())
    .then(data => {
      console.log(data) 
    });

Interceptación HTTP en Axios

La interceptación HTTP de Axios es una de las características clave de esta biblioteca, por eso no es necesario crear código adicional para utilizarla.

// interceptores de solicitudes
axios.interceptors.request.use((config)=>{
    console.log('Request was sent');
    return config;
})

// interceptores de respuesta
axios.interceptors.response.use((response) => {
    // hace una operación o respuesta
    return response; 
})

axios.get('url')
    .then((response)=>console.log(response))
    .catch((error)=>console.log(error))

En el código anterior, los métodos axios.interceptors.request.use() y axios.interceptors.response.use() se utilizan para definir el código que se ejecutará antes de enviar una solicitud HTTP.

Tiempo de respuesta (Response timeout)

Response timeout en Fetch

Fetch() proporciona la funcionalidad de tiempo de espera de la respuesta a través de la interfaz AbortController.

const controller = new AbortController();
const signal = controller.signal;
const options = {
  method: 'POST',
  signal: signal,
  body: JSON.stringify({
    firstName: 'Boris',
    lastName: 'Holyguard'
  })
};  
const promise = fetch('/login', options);
const timeoutId = setTimeout(() => controller.abort(), 5000);

promise
  .then(response => {/* maneja la respuesta */})
  .catch(error => console.error('timeout excedido'));

En el código anterior, utilizando el constructor AbortController.AbortController(), es necesario crear un objeto AbortController. El objeto AbortController le permite abortar posteriormente la solicitud. Como mencioné en mi artículo anterior, "Deep Insights Into JavaScript's Fetch API", hablamos de cómo signal es una propiedad de AbortController, que es de sólo lectura. signal proporciona una forma de comunicarse con una solicitud o de abortar la solicitud. Si el servidor no responde en menos de cinco segundos, la operación se termina llamando a controller.abort().

Response timeout en Axios

Utilizando la propiedad opcional timeout en el objeto config, se puede establecer el número de milisegundos antes de que se termine la petición.

axios({
    method: 'post',
    url: '/login',
    timeout: 5000,    // timeout de 5 segundos
    data: {
      firstName: 'Boris',
      lastName: 'Holyguard'
    }
  })
  .then(response => {/* maneja la respuesta */})
  .catch(error => console.error('timeout excedido'))

Una de las razones por las que los desarrolladores de JavaScript eligen Axios en lugar de fetch() es la facilidad para establecer el tiempo de espera.

 

Solicitudes concurrentes (Concurrent Requests)

Concurrent Requests en Fetch

Para realizar múltiples peticiones simultáneas, puedes utilizar el método incorporado Promise.all(). Simplemente pasa un array de peticiones fetch() a Promise.all() y luego una función asíncrona para manejar la respuesta.

Promise.all([
  fetch('https://api.github.com/users/sabesansathananthan'),
  fetch('https://api.github.com/users/rcvaram')
])
.then(async([res1, res2]) => {
  const a = await res1.json();
  const b = await res2.json();
  console.log(a.login + ' has ' + a.public_repos + ' public repos on GitHub');
  console.log(b.login + ' has ' + b.public_repos + ' public repos on GitHub');
})
.catch(error => {
  console.log(error);
});

Concurrent Requests en Axios

Puedes conseguir el resultado anterior utilizando el método axios.all() proporcionado por Axios. Pasa todas las peticiones de obtención como un array al método axios.all(). Asigna las propiedades del array de respuestas a variables separadas utilizando la función axios.spread(), así:

axios.all([
  axios.get('https://api.github.com/users/holyguard'), 
  axios.get('https://api.github.com/users/manoweb')
])
.then(axios.spread((obj1, obj2) => {
  // Both requests are now complete
  console.log(obj1.data.login + ' has ' + obj1.data.public_repos + ' public repos on GitHub');
  console.log(obj2.data.login + ' has ' + obj2.data.public_repos + ' public repos on GitHub');
}));

Retrocompatibilidad

compatibilidad con los navegadores mas antiguos.

Retrocompatibilidad con Fetch

Fetch() sólo es compatible con Chrome 42+, Safari 10.1+, Firefox 39+ y Edge 14+. La tabla de compatibilidad completa está disponible en “Can I Use?” Para implementar funciones similares a fetch() en navegadores web que no soportan Fetch(), puede utilizar fetch() con un polyfill como windows.fetch().
Para utilizar el polyfill de fetch, instálelo mediante este comando npm:

npm install whatwg-fetch --save

Si necesitas acceder a la implementación del polyfill por alguna razón, está disponible a través de las exportaciones:

import {fetch as fetchPolyfill} from 'whatwg-fetch'

window.fetch(...)   // use native browser version
fetchPolyfill(...)  // use polyfill implementation

Ten en cuenta que también podrías necesitar un polyfill de promesas en algunos navegadores antiguos.

Retrocompatibilidad con Axios

Axios no es como fetch(). Axios ofrece una amplia compatibilidad con los navegadores. Incluso navegadores antiguos como IE11 pueden ejecutar Axios sin problemas. La tabla de compatibilidad completa está disponible en la documentación de Axios.

Conclusión

Para la mayoría de sus necesidades de comunicación HTTP, Axios proporciona una API fácil de usar en un paquete compacto.
Hay algunas bibliotecas alternativas para la comunicación HTTP, como ky, un diminuto y elegante cliente HTTP basado en window.fetch; superagent, una pequeña y progresiva biblioteca de peticiones HTTP del lado del cliente basada en XMLHttpRequest.
Pero Axios es una mejor solución para aplicaciones con muchas peticiones HTTP y para aquellas que necesitan un buen manejo de errores o intercepciones HTTP.
En el caso de proyectos pequeños con sólo unas pocas llamadas a la API, fetch() puede ser una buena solución.

 
by Janeth Kent Date: 01-03-2021 javascript ajax fetch json axios visitas : 1371  
 
Janeth Kent

Janeth Kent

Licenciada en Bellas Artes y programadora por pasión. Cuando tengo un rato retoco fotos, edito vídeos y diseño cosas. El resto del tiempo escribo en MA-NO WEB DESIGN END DEVELOPMENT.

 
 
 

Artículos relacionados

Cómo enviar un correo electrónico desde un formulario de contacto HTML

En el artículo de hoy vamos a escribir sobre cómo hacer un formulario que funcione y que al pulsar ese botón de envío sea funcional y envíe el correo electrónico…

Cómo hacer un sitio web multilingüe sin redireccionamiento

Hoy, vamos a hablar de cómo implementar un simple selector de idioma en el sitio web estático o básico, sin necesidad de ningún backend o llamadas a la base de…

Comenzando con Bootstrap-Vue paso a paso

Hoy te mostraremos cómo usar BootstrapVue, describiremos el proceso de instalación y mostraremos la funcionalidad básica. El proyecto está basado en el framework CSS más popular del mundo - Bootstrap, para…

Creación de un sencillo spinner-loader CSS

En el artículo de hoy mostraremos cómo animar un loader básico que gira cuando se define alguna acción predefinida, como cargar una imagen. Eso se puede utilizar en un sitio…

Los mejores selectores de fechas para Bootstrap y tu aplicación

Los selectores de fecha son widgets que permiten a los usuarios elegir una sola fecha o rango de fechas y horas. Es un elemento habitual para todo usuario de Internet,…

Validación de formularios HTML usando BULMA y vanilla JavaScript

Hoy vamos a escribir sobre los formularios de contacto y cómo validarlos usando JavaScript. El formulario de contacto parece ser una de las características principales de toda página web básica. Es…

Cómo usar el efecto Parallax.Js en tu sitio web

Hoy vamos a escribir sobre el efecto de parallax, similar al desplazamiento de parallax, y cómo implementarlo para mejorar su página de aterrizaje. En webdev, dicen que primero el móvil…

Usando la API FETCH para hacer llamadas AJAX - Una promesa cumplida

En este artículo hablamos sobre lo que son las llamadas AJAX y cómo utilizarlas de forma tradicional, utilizando el objeto XMLHttpRequest (XHR). En resumen, gracias a las llamadas AJAX una…

Modo oscuro persistente con CSS y JS

Recientemente escribimos acerca de cómo hacer un modo de color o tema alternativo intercambiable, una característica muy útil y popular para los sitios web. El artículo de hoy tratará sobre…

Haciendo peticiones AJAX a una REST API usando vanilla JavaScript y XHR

Imagina que acabas de construir tu primera página web estática y te gustaría añadir alguna funcionalidad para hacerla más atractiva y generalmente más utilizable. Tal vez te gustaría entretener al…

Modo oscuro en el sitio web usando CSS y JavaScript

En el artículo de hoy vamos a aprender a construir más o menos estándar en estos días en las páginas web y que es el modo de color alternativo y…

Javascript: los operadores Spread y Rest

En el artículo de hoy vamos a hablar de una de las características de la versión ES6 (ECMAScript 2015) de JavaScript que es el operador Spreadasí como el operador Rest. Estas…

Utilizamos cookies propias y de terceros para mejorar nuestros servicios, elaborar información estadística y analizar tus hábitos de navegación. Esto nos permite personalizar el contenido que ofrecemos y mostrarte publicidad relacionada con tus preferencias. Clicando en ‘Acepta todas’ aceptas el almacenamiento de cookies en tu dispositivo para mejorar la navegación en el sitio web, analizar el tráfico y ayudar en nuestras actividades de marketing. También puedes seleccionar ‘Sólo cookies de sistema’ para aceptar sólo las cookies necesarias para que la web funcione, o puedes seleccionar las cookies que quieres activar clicando en ‘Configuración’

Acepta todas Sólo cookies de sistema Configuración