Desde que en el año 1999 Microsoft introdujera el objeto XMLHttpRequest en IE5.0, o como siempre lo hemos llamado, Ajax, los desarrolladores de frontend hemos tenido pocas opciones a la hora de traer o enviar información al servidor de forma asíncrona. Eso cambia ahora con la introducción de Fetch, un nuevo estándar, revisado para adaptarlo a los tiempos que corren, y que nos va a permitir hablar con el servidor sin usar AJAX.

Los puntos fuertes que tiene son:

  • Simplicidad de uso. Ya no es será necesario instanciar objetos y configurar "pseudocallbacks" para cuando la operación haya acabado.
  • Orientado a promesas. Nos guste o no, la programación asíncrona orientada a promesas está aquí para quedarse. Y esta nueva API está 100% enfocada a ella.

Soporte

El soporte de esta nueva función es aún extemadamente limitado, siendo solo 100% funcional en la versión Canary de Chrome y en la última de FireFox. Sin embargo, si deseas empezar a usarlo desde ya en tus proyectos, puedes usar el polyfill creado por la gente de Github.

Uso

El ejemplo más básico de uso es algo así:

fetch( "http://pokeapi.co/api/v1/pokemon/1/" )  
  .then( ( response ) => { return response.json() } )
  .then( (pokemon) => { console.log( pokemon ) } );

// Object {abilities: Array[2], attack: 49, catch_rate: 0, created: "2013-11-03T15:05:41.260678", defense: 49…}

Fetch puede tomar dos parámetros:

  • URL de la petición (obligatorio)
  • Opciones de configuración:
    • method: Por defecto será GET, pero puedes poner cualquiera válido.
    • header: Object, cuya clave será el nombre de la cabecera, y cuyo value será el valor de la cabecera.
    • body: Información a pasar al servidor. Normalmente lo usas en combinación a una petición POST. Puede ser uno de los siguientes objetos:
      • instancia de BLOB
      • instancia de FormData
      • Un string en formato QueryString. Por ej.: "key1=value1&key2=value2". Se utiliza para peticiones GET.
      • Un string arbitrario. Se utiliza sobre todo para cadenas JSON.
    • mode: Determinamos si vamos a hacer o no una llamada CORS.
    • credentials: Si deseas enviar información de seguridad al servidor como una cookie de sesión.
    • cache: Determinamos la estrategia de cacheo deseada, desde no cachear en absoluto hasta hacerlo solo si el recurso ha sido modificado.

Una vez que hemos llamado a la función Fetch, esta nos devuelve una promesa que será rechazada si el servidor responde con los códigos 4xx o 5xx, de manera similar a como lo hace jQuery.ajax.

En caso de no haber ningún error, nuestra promesa queda resuelta con una instancia de Response.

Los atributos más importantes de la respuesta son:

  • status: Nos devuelve en código de la respuesta del servidor.
  • statusText: "OK" si todo fue correcto.
  • url
  • headers: Esta es una instancia del objeto Header. Es un objeto que encapsula todas las cabeceras de la respuesta y podemos acceder a ellas, ya sea directamente o mediante un iterador, como puedes observar el siguiente ejemplo:
fetch( "http://pokeapi.co/api/v1/pokemon/1/" )  
  .then( ( response ) => {
    // Usando el iterador
    for( let [header, value] of response.headers ){
      console.log(`Header ${header}: ${value}`)
      }

    // O accediendo directamente
    console.log( `Acceso directo ${response.headers.get('cache-control')}` );

  } );

La salida de consola sería la siguiente:

Mediante la instancia response accedes al body de la respuesta. Es importante recordar que hasta que no esté completado no puedes acceder al body de la respuesta, puesto que el objeto response es un stream. Por lo tanto, lo que TODOS estos métodos devuelven es una promesa que se resuelve con el body de la respuesta formateado apropiadamente:

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

Un par de ejemplos de cómo puede interpretarse la respuesta del servidor:

  • Como un JSON:
const BASE_URL = "http://pokeapi.co/api/v1";

fetch( `${BASE_URL}/pokemon/1/` )  
  .then( (response) => { return response.json() } )
  .then( (pokemon) => { console.log( pokemon ) } );

Y esto es lo que genera:

  • Como un string genérico:
const BASE_URL = "http://pokeapi.co/api/v1";

fetch( `${BASE_URL}/pokemon/1/` )  
  .then( (response) => { return response.text() } )
  .then( (pokemon) => { console.log( pokemon ) } );

Y esto es lo que genera:

  • Como una instancia de Blob:
const BASE_URL = "http://pokeapi.co/api/v1";

fetch( `${BASE_URL}/pokemon/1/` )  
  .then( (response) => { return response.blob() } )
  .then( (pokemon) => { console.log( pokemon ) } );

Y esto es lo que genera:

Espero que hayas pillado el punto de lo que quiero decir. Recuerda que tú decides en qué formato quieres interpretar el cuerpo de la respuesta y esta siempre viene dentro de una promesa.

Por supuesto, puedes usar fetch, no solo para hacer peticiones GET al servidor, sino también para enviar datos ( POST ) o consultar las cabeceras de una petición ( HEAD ). Como puedes ver en estos ejemplos (tomados de la documentación de github/fetch):

var form = document.querySelector('form')

fetch('/query', {  
  method: 'post',
  body: new FormData(form)
})

Bonus

Como ya hemos comentado, fetch trabaja usando promesas. Si le echas un ojo al artículo de promesas y generadores podrías hacer cosas así:

co( function* (){

  let response = yield fetch( `${BASE_URL}/pokemon/1/` );
  let pokemon = yield response.json();

  return pokemon
} ).then( (pokemon) => { console.log( pokemon ) } );

Si te ha gustado este post, difunde la palabra. Tampoco dudes en dejar comentarios u observaciones. ¡Gracias! :)

Suscríbete a mi lista de correo

* Campos obligatorios