Recuperar API vs XMLHttpRequest

163

Sé que Fetch API usa Promisesy ambos le permiten hacer solicitudes AJAX a un servidor.

He leído que Fetch API tiene algunas características adicionales, que no están disponibles en XMLHttpRequest(y en el polyfill de Fetch API, ya que está basado en XHR).

¿Qué capacidades adicionales tiene la API Fetch?

ilyabasiuk
fuente
2
Aunque no puedo recordar en el acto, hay una o dos cosas que puedes hacer con XHR que no puedes con fetch. Dices que has leído que buscar tiene posibilidades adicionales, esos artículos no son muy buenos si no dicen lo que son
Jaromanda X
2
descubrió las dos cosas que no puede hacer con fetch que puede hacer con XHR ... no puede establecer su propio valor para el tiempo de espera de solicitud en fetch, ni puede obtener eventos de progreso
Jaromanda X
3
Fetch es solo una forma simplificada de hacer cosas para la mayoría de los tipos de XMLHttpRequests. Si su caso de uso se ajusta a lo que hace Fetch, úselo. Cuando llegas a eso, la API XMLHttpRequest es fea para lo que la mayoría de la gente usa. Fetch fue un esfuerzo por ofrecer una forma más limpia de hacer cosas que no necesitan una biblioteca envuelta alrededor de XMLHttpRequest para que sea aceptable.
jfriend00
1
Tiene soporte puro en los navegadores ( caniuse.com/#search=fetch ), por lo que hay un polifill para github.com/github/fetch , que funciona por encima de xhr
ilyabasiuk
44
@Marco - ¿Cómo puedes decir que fetch(url).then(function(data) (...));no es más simple que usar XMLHttpRequestpara hacer lo mismo? Puede tener muchas otras características, pero claro, es más fácil de usar para cosas comunes. Es una API limpiada.
jfriend00

Respuestas:

120

Hay algunas cosas que puede hacer con fetch y no con XHR:

  • Puede usar la API de caché con los objetos de solicitud y respuesta;
  • Puede realizar no-corssolicitudes, obteniendo una respuesta de un servidor que no implementa CORS. No puede acceder al cuerpo de respuesta directamente desde JavaScript, pero puede usarlo con otras API (por ejemplo, la API de caché);
  • Transmisión de respuestas (con XHR, toda la respuesta está almacenada en la memoria, con fetch podrá acceder a la transmisión de bajo nivel) Esto aún no está disponible en todos los navegadores, pero lo estará pronto.

Hay un par de cosas que puedes hacer con XHR que aún no puedes hacer con fetch, pero estarán disponibles tarde o temprano (lee el párrafo "Mejoras futuras" aquí: https: //hacks.mozilla .org / 2015/03 / this-api-is-so-fetching / ):

  • Cancelar una solicitud (esto ahora funciona en Firefox y Edge, como explica @sideshowbarker en su comentario);
  • Informar sobre el progreso.

Este artículo https://jakearchibald.com/2015/thats-so-fetch/ contiene una descripción más detallada.

Marco
fuente
1
La especificación para la API Fetch ahora proporciona la cancelación. El soporte se ha enviado hasta ahora en Firefox 57 y Edge 16. Demostraciones: fetch-abort-demo-edge.glitch.me , mdn.github.io/dom-examples/abort-api . Y hay errores de funciones de Chrome y Webkit abiertos bugs.chromium.org/p/chromium/issues/detail?id=750599 , bugs.webkit.org/show_bug.cgi?id=174980 . Cómo hacerlo: developers.google.com/web/updates/2017/09/abortable-fetch , developer.mozilla.org/en-US/docs/Web/API/AbortSignal#Examples . Y ejemplo en la respuesta de desbordamiento de pila en stackoverflow.com/a/47250621/441757
sideshowbarker
1
Otra diferencia es que las fetchsolicitudes no se pueden reproducir en las Herramientas para desarrolladores.
Parziphal
Y, según mi experiencia, fetchpuede solicitar archivos, pero XHR no.
D. Pardal
64

ir a buscar

  • Falta un método incorporado para consumir documentos
  • no hay forma de establecer un tiempo de espera todavía
  • no puede anular el encabezado de respuesta de tipo de contenido
  • si el encabezado de respuesta de longitud de contenido está presente pero no expuesto , la longitud total del cuerpo se desconoce durante la transmisión
  • llamará al controlador de cancelación de la señal incluso si la solicitud se ha completado
  • sin progreso de carga (soporte para ReadableStreaminstancias ya que los cuerpos de solicitud aún están por llegar )

XHR

  • no hay forma de no enviar cookies (aparte de usar el indicador no estándarmozAnon o el AnonXMLHttpRequestconstructor)
  • no puede devolver FormDatainstancias
  • no tiene un equivalente a fetch's no-corsmodo de
  • siempre siga las redirecciones
Knu
fuente
13
fetchTambién le falta progreso. con XHR puedes seguir el progreso del progressevento
rzr
1
"no se puede anular el encabezado de tipo de contenido de la respuesta" ... para empezar, es solo una mala idea. el 'tipo de contenido dicta lo que se debe devolver y el BACKEND DEBE dictar eso a la interfaz de usuario. DE HECHO, el tipo de contenido debe ser el 'ÚNICO ENCABEZADO' para el tipo porque lo que se solicita es lo que debe devolverse. Si desea algo diferente, sirva desde un subdominio especial o algo así puede manejar la funcionalidad específica por separado. Estás tratando de forzar una regla del 1% hacia abajo del 99% de la garganta de todos.
Orubel
@Knu sí, ahora estamos más avanzados y podemos automatizar fácilmente una solución del 90% y dejar que los casos extraños se dirijan a una funcionalidad diferente.
Orubel
1
@rzr no exactamente, lo tienes Response#body.
Knu
9

Las respuestas anteriores son buenas y proporcionan buenas ideas, pero comparto la misma opinión que la que compartí en esta entrada del blog de desarrolladores de Google en que la principal diferencia (desde una perspectiva práctica) es la conveniencia de la promesa incorporada devuelta defetch

En lugar de tener que escribir código como este

function reqListener() {
    var data = JSON.parse(this.responseText);
}

function reqError(err) { ... }

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

podemos limpiar las cosas y escribir algo un poco más conciso y legible con promesas y sintaxis moderna

fetch('./api/some.json')
    .then((response) => {
        response.json().then((data) => { 
            ... 
        });
    })
    .catch((err) => { ... });
Felipe
fuente
8
@TheOpti Puede realizar polyfill de soporte de búsqueda básica en IE 11. También podría simplemente soltar IE11 como un navegador compatible en muchos proyectos, ya que en muchas bases de usuarios, el uso de IE 11 ahora está por debajo del 1%.
Devon Holcombe