We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del inglés.

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 de la tubería 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 a HTTP.

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

  • La promesa devuelta desde fetch() no se rechazara en el estado de error de HTTP incluso si la respuesta es un HTTP 404 o 500. En cambio, este se resolverá normalmente (con un estado ok configurado en falso), y  este solo sera rechazado en una falla de red o si algo impidio completar la solicitud.
  • Por defecto, fetch no enviara ni recibirá cookies del servidor, resultando en peticiones no autenticadas si el sitio permite en mantenimiento una sesión de usuario (para mandar cookies, las credenciales de opcion de inicio deberan ser configuradas).

Estado del soporte en navegadores

El soporte para Fetch está aún en una etapa bastante temprana, pero se están haciendo progresos. Viene habilitado por defecto en Firefox 39, Chrome 42 y en versiones posteriores de ambos.

Si quiere utilizarlo ahora, también está disponible un Fetch Polyfill que recrea la funcionalidad para los navegadores que no la soporten. Tenga en cuenta que esto se encuentra en una etapa experimental y aún no completa.

Nota: There have been some concerns raised that the Fetch spec is at odds with the Streams spec; however, future plans show an intention to integrate Streams with Fetch: read Fetch API integrated with Streams for more information.

Detección de característica

El soporte de la API Fetch se puede detectar comprobando la existencia de Headers, Request, Responsefetch() en el contexto Window o Worker. Por ejemplo, debería hacer esto en su script:

if(self.fetch) {
    // ejecutar petición fetch
} else {
    // ¿hacer algo con XMLHttpRequest?
}

Realizando peticiones fetch

Es muy fácil configurar una petición fetch. Eche un vistazo al siguiente código:

var miImagen = document.querySelector('img');

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

Aquí estamos cargando una imagen a través de la red e insertándola en un elemento <img>. El uso más simple de fetch() toma un argumento — la ruta del recurso que se quiera traer — y devuelve una promesa que contiene la respuesta (un objeto Response).

Por supuesto, esto es sólo una respuesta HTTP, no la imagen actual. Para extraer el contenido del cuerpo de la imagen de la respuesta empleamos el método blob() (definido en el Body mixin, el cual es  implementado tanto por Request como objetos de Response.)

Note: The Body mixin also has similar methods to extract other types of body content; see the Body section for more.

Un objectURL se crea del Blob extraído, que es insertado en img.

Las peticiones Fetch son controladas por la directiva connect-src de Content Security Policy en lugar de la directiva del recurso que está recuperando.

Suministrando opciones de petición

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

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;
});

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

Comprobando que la petición es satisfactoria

Una promesa 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('flowers.jpg').then(function(response) {
  if(response.ok) {
    response.blob().then(function(myBlob) {
      var objectURL = URL.createObjectURL(myBlob);
      myImage.src = objectURL;
    });
  } else {
    console.log('Network response was not ok.');
  }
})
.catch(function(error) {
  console.log('There has been a problem with your fetch operation: ' + error.message);
});

Proporcionando tu propio objeto de petición

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.

Cabeceras

La interfaz Headers te permite crear tus propios objetos de cabeceras mediante el constructor Headers(). Un objeto de cabecera 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");

lo mismo se pued 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, lo que provee al API mejor para manipular cabeceras.

All of the Headers methods throw a TypeError if a header name is used that is not a valid HTTP Header name. The mutation operations will throw a TypeError if there is an immutable guard (see below). Otherwise they fail silently. For example:

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

A good use case for headers is checking whether the content type is correct before you process it further. For example:

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!");
  }
});

Guard

Since headers can be sent in requests and received in responses, and have various limitations about what information can and should be mutable, headers objects have a guard property. This is not exposed to the Web, but it affects which mutation operations are allowed on the headers object.

Possible guard values are:

  • none: por defecto.
  • request: guard for a headers object obtained from a request (Request.headers).
  • request-no-cors: guard for a headers object obtained from a request created with Request.mode no-cors.
  • response: guard for a Headers obtained from a response (Response.headers).
  • immutable: Mostly used for ServiceWorkers; renders a headers object read-only.

Note: You may not append or set a request guarded Headers’ Content-Length header. Similarly, inserting Set-Cookie into a response header is not allowed: ServiceWorkers are not allowed to set cookies via synthesized responses.

Objetos de respuesta

As you have seen above, Response instances are returned when fetch() promises are resolved.

They can also be created programmatically via JavaScript, but this is only really useful in ServiceWorkers, when you are providing a custom response to a received request using a respondWith() method:

var myBody = new Blob();

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

The Response() constructor takes two optional arguments — a body for the response, and an init object (similar to the one that Request() accepts.)

The most common response properties you'll use are:

  • Response.status — An integer (default value 200) containing the response status code.
  • Response.statusText — A string (default value "OK"),which corresponds to the HTTP status code message.
  • Response.ok — seen in use above, this is a shorthand for checking that status is in the range 200-299 inclusive. This returns a Boolean.

Note: The static method error() simply returns an error response. Similarly, redirect() returns a response resulting in
a redirect to a specified URL. These are also only relevant to Service Workers.

Body

Both requests and responses may contain body data. A body is an instance of any of the following types.

The Body mixin defines the following methods to extract a body (implemented by both Request and Response). These all return a promise that is eventually resolved with the actual content.

This makes usage of non-textual data much easier than it was with XHR.

Request bodies can be set by passing body parameters:

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

Both request and response (and by extension the fetch() function), will try to intelligently determine the content type. A request will also automatically set a Content-Type header if none is set in the dictionary.

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: icedrek, royexr, AlePerez92
Última actualización por: icedrek,