Esta es una tecnología experimental
Comprueba la Tabla de compabilidad de navegadores cuidadosamente antes de usarla en producción.

La API Fetch proporciona una interfaz JavaScript para acceder y manipular partes del canal HTTP, como peticiones y respuestas. También provee un método global fetch() que proporciona una forma fácil y lógica de obtener recursos de forma asíncrona por la red.

Este tipo de funcionalidad se conseguía previamente haciendo uso de XMLHttpRequest. Fetch proporciona una mejor alternativa que puede ser empleada fácilmente por otras tecnologías como Service Workers. Fetch también aporta un único lugar lógico en el que definir otros conceptos relacionados con HTTP como CORS y extensiones para HTTP.

La especificación fetch difiere de JQuery.ajax() en dos formas principales:

  • El objeto Promise devuelto desde fetch() no será rechazado con un estado de error HTTP incluso si la respuesta es un error HTTP 404 o 500. En cambio, este se resolverá normalmente (con un estado ok configurado a false), y  este solo sera rechazado ante un fallo de red o si algo impidio completar la solicitud.

  • Por defecto, fetch no enviará ni recibirá cookies del servidor, resultando en peticiones no autenticadas si el sitio permite mantentener una sesión de usuario (para mandar cookies, credentials de la opción init deberan ser configuradas). Desde el 25 de agosto de 2017. La especificación cambió la politica por defecto de las credenciales a same-origin. Firefox cambió desde la versión 61.0b13.

Una petición básica de fetch es realmente simple de establecer. Eche un vistazo el siguente código:

fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

Aquí estamos recuperando un archivo JSON a través de red e impriminedola en la consola. El más simple uso de fetch() toma un argumento (la ruta del recurso que quieres obtener) y devuelve un objeto Promise conteniendo la respuesta, un objeto Response.

Esto es, por supuesto, una respuesta HTTP no el archivo JSON. Para extraer el contenido en el cuerpo del JSON desde la respuesta, usamos el método json() (definido en el mixin de Body, el cual está implementado por los objetos Request y Response).

Nota: El mixin de Body tambien tiene metodos parecidos para extraer otros tipos de contenido del cuerpo. Vease Body para más información.

Las peticiones de Fetch son controladas por la directiva de connect-src de Content Security Policy en vez de la directiva de los recursos que se han devuelto.

Suministrando opciones de petición

El método fetch() puede aceptar un segundo parámetro opcional, un objeto init que permite controlar algunos ajustes:

Vea fetch(), para ver todas las opciones disponibles y más detalles.

var misCabeceras = new Headers();

var miInit = { method: 'GET',
               headers: misCabeceras,
               mode: 'cors',
               cache: 'default' };

fetch('flores.jpg',miInit)
.then(function(response) {
  return response.blob();
})
.then(function(miBlob) {
  var objectURL = URL.createObjectURL(miBlob);
  miImagen.src = objectURL;
});

Comprobando que la petición es satisfactoria

Una petición promise fetch() será rechazada con TypeError cuando se encuentre un error de red, aunque esto normalmente significa problemas de permisos o similares — por ejemplo, un 404 no constituye un error de red. Una forma precisa de comprobar que la petición fetch() es satisfactoria pasa por comprobar si la promesa ha sido resuelta, además de comprobar que la propiedad Response.ok tiene el valor true. El código sería algo así:

fetch('flores.jpg').then(function(response) {
  if(response.ok) {
    response.blob().then(function(miBlob) {
      var objectURL = URL.createObjectURL(miBlob);
      miImagen.src = objectURL;
    });
  } else {
    console.log('Respuesta de red OK.');
  }
})
.catch(function(error) {
  console.log('Hubo un problema con la petición Fetch:' + error.message);
});

Proporcionando tu propio objeto Request

En lugar de pasar la ruta al recurso que deseas solicitar a la llamada del método fetch(), puedes crear un objeto de petición utilizando el constructor Request(), y pasarlo como un argumento del método fetch():

var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

var myRequest = new Request('flowers.jpg', myInit);

fetch(myRequest)
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

Request() acepta exactamente los mismos parámetros que el método fetch(). Puedes incluso pasar un objeto de petición existente para crear una copia del mismo:

var anotherRequest = new Request(myRequest, myInit);

Esto es muy útil ya que el cuerpo de las solicitudes y respuestas son de un sólo uso. Haciendo una copia como esta te permite utilizar la petición/respuesta de nuevo, y al mismo tiempo, si lo deseas, modificar las opciones de init. La copia debe estar hecha antes de la lectura del <body>, y leyendo el <body> en la copia, se marcará como leido en la petición original.

Nota: Existe también un método clone() que crea una copia. Este tiene una semántica ligeramente distinta al otro método de copia — el primero fallará si el cuerpo de la petición anterior ya ha sido leído (lo mismo para copiar una respuesta), mientras que clone() no.

Enviar una petición con credenciales incluido

Para producir que los navegadores envien una petición con las credenciales incluidas, incluso para una llamada de origen cruzado, añadimos credentials: 'include' en el el objeto init que se pasa al método fetch().

fetch('https://example.com', {
  credentials: 'include'  
})

Si solo quieres enviar la credenciales si la URL de la petición está en el mismo origen desde donde se llamada el script, añade credentials: 'same-origin'.

// El script fué llamado desde el origen 'https://example.com'

fetch('https://example.com', {
  credentials: 'same-origin'  
})

Sin embargo para asegurarte que el navegador no incluye las credenciales en la petición, usa credentials: 'omit'.

fetch('https://example.com', {
  credentials: 'omit'  
})

Enviando datos JSON

Usa fetch() para enviar una petición POST con datos codificados en JSON .

var url = 'https://example.com/profile';
var data = {username: 'example'};

fetch(url, {
  method: 'POST', // or 'PUT'
  body: JSON.stringify(data), // data can be `string` or {object}!
  headers:{
    'Content-Type': 'application/json'
  }
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

Enviando un archivo

Los archivos pueden ser subido mediante el HTML de un elemento input <input type="file" />, FormData() y fetch().

var formData = new FormData();
var fileField = document.querySelector("input[type='file']");

formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);

fetch('https://example.com/profile/avatar', {
  method: 'PUT',
  body: formData
})
.then(response => response.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

Cabeceras

La interfaz Headers te permite crear tus propios objetos de headers mediante el constructor Headers(). Un objeto headers es un simple multi-mapa de nombres y valores:

var content = "Hello World";
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

Lomismo se puede lograr pasando un "array de arrays" o un objeto literal al constructor:

myHeaders = new Headers({
  "Content-Type": "text/plain",
  "Content-Length": content.length.toString(),
  "X-Custom-Header": "ProcessThisImmediately",
});

Los contenidos pueden ser consultados o recuperados:

console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue");
 
console.log(myHeaders.get("Content-Length")); // 11
console.log(myHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]
 
myHeaders.delete("X-Custom-Header");
console.log(myHeaders.getAll("X-Custom-Header")); // [ ]

Algunas de estas operaciones solo serán utiles en  ServiceWorkers, pero estas disponen de una mejor API  para manipular headers.

Todos los métodosde de headers lanzan un TypeError si un nombre de cabecera no es un nombre de cabecera HTTP válido. Las operaciones de muntación lanzarán un TypeError si hay un guarda inmutable (ver más abajo). Si no, fallan silenciosamente. Por ejemplo:

var myResponse = Response.error();
try {
  myResponse.headers.set("Origin", "http://mybank.com");
} catch(e) {
  console.log("Cannot pretend to be a bank!");
}

Un buen caso de uso para headers es comprobar cuando el tipo de contenido es correcto antes de que se procese:

fetch(myRequest).then(function(response) {
  var contentType = response.headers.get("content-type");
  if(contentType && contentType.indexOf("application/json") !== -1) {
    return response.json().then(function(json) {
      // process your JSON further
    });
  } else {
    console.log("Oops, we haven't got JSON!");
  }
});

Guarda (Guard)

Desde que las cabeceras pueden ser enviadas  en peticiones y recibidas en respuestas, y tienen limitaciones sobre que información puede y debería ser mutable, los objeto headers tienen una propierdad de guarda. Este no está expuesto a la Web, pero puede afectar a que operaciones de mutación son permitidas sobre el objeto headers.

Los valores posibles de guarda (guard) son:

  • none: valor por defecto.
  • request: Guarda para el objeto headers obtenido de la petición (Request.headers).
  • request-no-cors: Guarda para un objeto headers obtenido desde una petición creada con Request.mode a no-cors.
  • response: Guarda para una cabecera obetenida desde un respuesta (Response.headers).
  • immutable: Mayormente utilizado para ServiceWorkers, produce un objeto headers de solo lectura.

Nota:  No se devería añadir o establecer una petición a un objeto headers guardado con la cabecera Content-Length. De igual manera, insertar Set-Cookie en la respuesta de la cabecera no esta permitido: ServiceWorkers no estan autorizados a establecer cookies a través de respuestas sintéticas.

Objetos Response

Cómo has visto anteriormente, las instancias de Response son devueltas cuando fetch() es resuelto.

Las propiedades de response que usarás son:

  • Response.status — Entero (por defecto con valor 200) que contiene el código de estado de las respuesta.
  • Response.statusText — Cadena (con valor por defecto "OK"), el cual corresponde al mensaje del estado de código HTTP.
  • Response.ok — Visto en uso anteriormente, es una clave para comporbar que el estado está dentro del rango 200-299 incluido. Este devuelve un valor Boolean.

Estos pueden tambíen creados programaticamente a través de JavaScript, pero esto solo es realmete util en ServiceWorkers,  cuando pones un objeto response personalizado a una respuesta recivida usando un método respondWith():

var myBody = new Blob();

addEventListener('fetch', function(event) {
  event.respondWith(
    new Response(myBody, {
      headers: { "Content-Type" : "text/plain" }
    })
  );
});

El constructor Response() toma dos argurmentos opcionales, un cuerpo para la respuesta y un objeto init (similar al que acepta Request()).

 

Nota: El método estático error() simplemente devuelve un error en la respuesta. De igual manera que redirect() devuelve una respuesta que resulta en un redirección a una URL especificada. Estos son solo relevantes tambien a ServiceWorkers.

 

Body

Tanto las peticiones como las respuestas pueden contener datos body. Body es una instancia de cualquiera de los siguientes tipos:

El mixin de Body define los siguientes metodos para extraer un body (implementado por {domxref("Request")}} and Response). Todas ellas devuelven una promesa que es eventualmente resuelta con el contenido actual.

Este hace uso de los datos no texttuales mucho mas facil que si fuera con XHR.

Las peticiones body pueden ser establecidas pasando el parametro body:

var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
  method: "POST",
  body: form
});

Tanto peticiones y respuestas (y por extensión la function fetch()), intentaran inteligentemente determinar el tipo de contenido. Una petición tambien establecerá automáticamente la propiedad Context-Type de la cabecera si no es ha establecido una.

Detectar caracteristica

Saber si el explorador tiene soporte, puede ser detectado comprobando la existencia de Headers, Request, Response o fetch() sobre el ámbito de Window o Worker. Por ejemplo:

if (self.fetch) {
    // run my fetch request here
} else {
    // do something with XMLHttpRequest?
}

Polyfill

Para utilizar fetch() en un explorador no soportado, hay disponible un Fetch Polyfill que recrea la funcionalidad para navegadores no soportados.

Especificaciones

Especificación Estado Comentario
Fetch Living Standard Definición inicial

Compatibilidad en navegadores

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

Característica Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Soporte básico 42
41 behind pref
 
14 39 (39)
34 behind pref
Sin soporte

29
28 behind pref

Sin soporte
Característica Android Firefox Mobile (Gecko) Firefox OS (Gecko) IE Phone Opera Mobile Safari Mobile Chrome para Android
Soporte básico 5-6.x Sin soporte Sin soporte Sin soporte 37 Sin soporte 55

Vea también

Etiquetas y colaboradores del documento

Colaboradores en esta página: anjerago, icedrek, royexr, AlePerez92
Última actualización por: anjerago,