Utilizando Fetch

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

This is an experimental technology
Because this technology's specification has not stabilized, check the compatibility table for usage in various browsers. Also note that the syntax and behavior of an experimental technology is subject to change in future versions of browsers as the specification changes.

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.

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.

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

The Headers interface allows you to create your own headers object via the Headers() constructor. A headers object is a simple multi-map of names to values:

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

The same can be achieved by passing an array of arrays or an object literal to the constructor:

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

The contents can be queried and retrieved:

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")); // [ ]

Some of these operations are only useful in ServiceWorkers, but they provide a much nicer API for manipulating headers.

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

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

29
28 behind pref

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

Vea también

Etiquetas y colaboradores del documento

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