Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Fetch - Cómo cancelar peticiones

20/42
Recursos

La peticiones AJAX permitieron en su tiempo hacer peticiones asíncronas al servidor sin tener que detener la carga de la página. Hoy en día se utiliza la función fetch para esto.

Con fetch tenemos algo llamado AbortController que nos permite enviar una señal a una petición en plena ejecución para detenerla.

Aportes 91

Preguntas 12

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Ey chicos me tome el tiempo para traerles las mejores notas del curso, denle una checada porfavor a mis notas, y si son de su agrado dejenme un like en github. Saludos 😄
Notas o https://github.com/JasanHdz/javascript-professional/tree/master/notes

Apuntes de la clase

Todos simulando una conexión lenta mientras yo vivo en ella 😄 saludos de Venezuela

Dejo el código del inicio para el que lo necesite:

<html>
  <head>
    <title>Abort Fetch</title>
  </head>
  <body>
    <a href="/ejercicios/">Go back</a>
    <p><em>Abre la consola</em></p>

    <img 
        id="huge-image" 
        height="400"
    />
    <button id="load">Load HUGE Image</button>
    <button id="stop" disabled>Stop Fetching</button>
    
    <script>
        const url = 
        'https://images.pexels.com/photos/974470/nature-stars-milky-way-galaxy-974470.jpeg?q=100';
      const img = document.getElementById('huge-image');
      const loadButton = document.getElementById('load');
      const stopButton = document.getElementById('stop');


      function startLoading() {
        loadButton.disabled = true;
        loadButton.innerText = 'Loading...';
        stopButton.disabled = false;
      }
      function stopLoading() {
        loadButton.disabled = false;
        loadButton.innerText = 'Load HUGE Image';
        stopButton.disabled = true;
      }

      loadButton.onclick = async function() {
        startLoading();
        stopLoading();
      };

      stopButton.onclick = function() {
        stopLoading();
      };
    </script>
  </body>
</html>

El método fetch abrirá un canal de comunicación con un recurso externo (en red) devolviendo una promesa, por lo tanto se puede acceder a la respuesta mediante un then.

fetchResponsePromise = fetch(resource, init);

Como todas las promesas se puede acceder a la respuesta dentro de funciones async, mediante al el uso de la palabra reservada await y de esta manera utilizar de manera más sencilla la respuesta.

fetch(myRequest).then(function(response) {
	// code
});

fetch historicamente proviene del XMLHttpReques (o XHR para los cuates) con un funcionamiento similar al JQUERY.ajax (Asyncronous JavaScript And XML) con un mejor manejo de los errores (ya que fetch sólo fallará cuando hayan problemas de red, manejando los errores mediante Response.status, Response.statusText y Response.ok).
.
Una de las ventajas adicionales que se manejan con fetch vs XHR, es que fetch permite la cancelación de una señal (signal) mediante objetos de tipo AbortController.
.
Para conseguir la señal interrumpida se debe de configurar un objeto de tipo AbortController, mismo que tiene una objeto de tipo AbortSignal, que es el que especificará si la señal se ha interrumpido o no (mediante AbortSignal.aborted)

let controller =  new AbortController()

En el objeto de configuración del await existe un atributo llamado signal que recibe una señal de tipo AbortSignal (para este caso se guardó en el controller).

const response = await fetch(url, {signal: controller.signal});

Para parar la señal, sólo debemos acceder al método abort() del AbortController que genera el AbortSignal

controller.abort();

No me hizo falta hacer ninguna modificación en el inspector de google…

blob es el binario de la petición que estamos pidiendo.

const response = await fetch(url);
const blob = await response.blob();
  • Este binario no se puede pasar directamente a la imagen, hay que convertirlo a una url.
    – El navegador trae una utilidad para realizar ese paso: URL.createObjectURL()
const imgUrl = URL.createObjectURL(blob);

➡️Mas información:
blob(): https://developer.mozilla.org/en-US/docs/Web/API/Body/blob
blob: https://developer.mozilla.org/es/docs/Web/API/Blob
URL.createObjectURL(): https://developer.mozilla.org/es/docs/Web/API/URL/createObjectURL

AbortController.abort ()

El método abort() de la la interfaz AbortController. Esta interfaz anula una solicitud DOM (por ejemplo, una solicitud Fetch) antes de que se haya completado. Esto puede abortar las solicitudes de recuperación, el consumo de cualquier respuesta Bodyy las transmisiones.

Sintaxis

controller.abort();

Ejemplos

En el siguiente fragmento, nuestro objetivo es descargar un video usando la API Fetch .

Primero creamos un controlador usando el AbortController()constructor, luego tomamos una referencia a su AbortSignalobjeto asociado usando la AbortController.signalpropiedad.

Cuando se inicia la solicitud de búsqueda , pasamos el AbortSignalcomo una opción dentro del objeto de opciones de la solicitud (ver más {signal}abajo). Esto asocia la señal y el controlador con la solicitud de recuperación y nos permite abortarla llamando AbortController.abort(), como se ve a continuación en el segundo detector de eventos.

var controller = new AbortController();
var signal = controller.signal;

var downloadBtn = document.querySelector('.download');
var abortBtn = document.querySelector('.abort');

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', function() {
  controller.abort();
  console.log('Download aborted');
});

function fetchVideo() {
  ...
  fetch(url, {signal}).then(function(response) {
    ...
  }).catch(function(e) {
    reports.textContent = 'Download error: ' + e.message;
  })
}

Nota : Cuando abort()se llama, la fetch()promesa se rechaza con un AbortError.

Puede encontrar un ejemplo de trabajo completo en GitHub: vea abort-api ( vea también cómo se ejecuta en vivo ).

Recuerden deshabilitar el cache en esta practica 👀

si el usuario no esta bendecido con una internet rápida 🤣

recuerden deshabilitar su cache en un checkbox que esta en network.
si necesitas una imagen mas pesada

img

Los BLOB (Binary Large Objects, objetos binarios grandes) son elementos utilizados en las bases de datos para almacenar datos de gran tamaño que cambian de forma dinámica. No todos los Sistemas Gestores de Bases de Datos son compatibles con los BLOB.

Generalmente, estos datos son imágenes, archivos de sonido y otros objetos multimedia; a veces se almacenan como códigos de binarios BLOB.

¿Qúe diferencia hay en usar addEventListener() y usar onclick?

Tuve que ver el video como 4 veces pero me sirvió, lo entendí al final

🔧Les recomiendo que para el manejo de errores no usen console.log sino console.error

Soy nuevo en JS así que entiendo poco de los botones y llamados pero el concepto es claro.

Que explicaciones tan malas por que abortan los temas tan rapido

No entiendo como es que la funcion stopButton.onclick puede acceder a controller.abort(), si controller = new AbortController fue definido en loadButton.onclick?

les dejo otro ejemplo del abort

ejemplo:

/***
 * Supongamos que tenemos una request y queremos cancelarla si la misma tarda mas mas de 2 segundos. 
**/

// aca tenemos el fetch comun y corriente
const url = "https://images.pexels.com/photos/974470/nature-stars-milky-way-galaxy-974470.jpeg?q=100";
let imgUrl

const respose = await fetch(url);
const blob = await respose.blob();
imgUrl = URL.createObjectURL(blob);
/**
 * Ahora para poder cancelar el fecth necesitamos usar el AbortController
**/
const url = "https://images.pexels.com/photos/974470/nature-stars-milky-way-galaxy-974470.jpeg?q=100";
let imgUrl

//1. instanciamos el controller 
const controller = new AbortController();

// 2. lo que vamos a hacer es un timmer, que si en 2 segundos no se resolvio la imgUrl cancelamos el fetch 

setTimeout(()=>{if(!imgUrl) controller.abort()},2000)

//3. ahora debemos pasarle al fetch el method signal como option
const respose = await fetch(url, {signal: controller.signal});
const blob = await respose.blob();
imgUrl = URL.createObjectURL(blob);

Que interesante!!

Bastante interesante !

yo creia que sabia algo de js, gracias por el contenido

Mi primer encuentro con fetch no fue tan grato, no lograba obtener la respuesta creo que por problemas de cors.

Decidí implementar axios y con mi compañero de trabajo nos solucionó toda la parte de comunicación con el servidor.

Alguien esta trabajando en proyectos reales con fetch o prefieren una librería como axios? Yo soy de esas personas que prefieren usar lo nativo y no sobrecargar los proyectos de librerías, pero por encima esta siempre la practicidad.

BLOB son las siglas de Binary Large Object

Lo mejor es que no tuve que simular un internet lento, ya lo tengo de 1mb 😉

URL.createObjectUrl([blob]) --> This help us to create an object based on a blob format. (images, json, etc) --> All the browsers have this feature to convert and use this.

Gracias, no conocía este método para cancelar fetch, así que lo que hacía era cancelar “Promise” utilizando otro promise para los resultados. No era muy limpio, debido a que la manera de cancelar el “Promise” era hacer “reject” de la “Promise” que encapsulaba la “Promise” del fetch.

Aquí más referencias de como hacer “Promise” que se puedan cancelar: https://medium.com/@masnun/creating-cancellable-promises-33bf4b9da39c#:~:text=There are reliable open source solutions for cancellable promises.&text=A function%2C when called%2C would,return it to the caller.

  1. Para mostrar errores en consola cuando usamos la estructura try/catch podemos usar
console.error()
  1. Blob = Binary Large OBject

Mi Bro (Jasanhdz) genial tu aporte, enserio muchas gracias por tomarte el tiempo y la dedicación te quedo genial lo sugeriré para otros q conozco que les gusta el lenguaje.

Creo que algo que es necesario aclarar que el profesor no explicó es que Fetch puede recibir opcionalmente un objeto de configuración en este caso allí es donde pasamos la señal del controller para luego usar el controller.abort(). 😄

Casi que no lo logro recrear, al final me salió pero es muy buena idea tener la opcion de cancelar un fetch.

No se si solo sea yo, pero me gustaría que subieran el archivo en que se trabaja (abort-fetch.html) como se empieza en la clase, no cuando lo modifican. Sería bueno para tener listo el punto de partida.

  • Los Blobs representan datos que no necesariamente se encuentran en un formato nativo de JavaScript. … por ejemplo pasa este dato de imagen lo pasa a binario y asi empezamos a jugar con el en JS.

  • Con URL.createObjectURL(blob) obenemos una url la cual el DOM entiende (img.src) pasándole por parámetro un binario en este caso el blob.

Con fetch tenemos algo llamado AbortController que nos permite enviar una señal a una petición en plena ejecución para detenerla.

Interesante… muchas gracias!!

Profesor: "Si el usuario no está bendecido con una conexión de internet rápida esto puede ser horrible"
Yo: 😩

repetí la clase como 3 o mas veces
pero creo que lo entendí

Fetch tenia un problema antes, al salir una petición hacia una API era imposible cancelar dicha petición, por lo que si haciamos una petición que no queriamos y queriamos seguir navegando normalmente habría que esperar hasta que dicha petición se concluyera para luego seguir navegando. Para solucionar eso llegó AbortController, al realizar la petición con fetch asíncronamente, y al traer los datos de la url, existe un método llamado “blob()” que convierte el response del fetch en código binario, pero en este caso estamos usando una imagen como response, por lo que no podemos pasarle a la función un código binario sino convertir ese codigo a URL. Para lograr eso, todos los navegadores tienen incorporado un método llamado URL.createObjectURL() y lo que hay que pasarle es el código binario o el blob que hicimos del fetch a la url de la imagen, y el navegador se encargará de convertir el blob o código binario a URL, y es esa URL la que utilizaremos para asignarle a la imagen
.
Luego por si la imagen tarde mucho implementaremos lo que viene siendo el tema de clase, cancelar dicha petición mientras esta tarde mucho, para eso pasaremos un objeto de configuración en el fetch a la url, y pasaremos un signal, de donde vendrá dicho signal? Aquí es donde entra AbortController, que nos dará los controles para poder cancelar una petición. AbortController es una clase, por lo que hay que instanciarla. AbortController tiene señales, que es la que nuestro atributo del objeto de configuración signal necesita. Luego cuando querramos detener la ejecución realmente, con el boton designado para eso, usamos el método abort de AbortController. Cabe destacar que nuestro AbortController debe tener un scope global para un mejor uso, ya que cuando lo instanciamos estamos usando en la función de cargar la imagen, por lo que esa instancia debe tener scope global para poder acceder también al botón disparador del cancelamiento de la petición, y para realizar el cancelador simplemente tenemos que ejecutar el método abort() del AbortController

A mi incluso con Slow 3G me carga muy rápido

Gente, me apoye en este video para reforzar https://www.youtube.com/watch?v=cjrt3NilcNw

muy bueno, entiendo que con fetch y blob y URL.createObjectUrl() podrías consultar algún recurso que necesite autorización (ejemplo una imagen privada o un vídeo ) y si la auth es correcta servirlo en el navegador. Supongo que Platzi y los videos debería función similar, tengo que tener sesión iniciada y permisos para acceder al recurso del video

Introduccion de la clase
La peticiones AJAX permitieron en su tiempo hacer peticiones asíncronas al servidor sin tener que detener la carga de la página.
Esto llego con un método llamado XMLhttprequest, usarlo era laborioso, mucho proceso para hacer una petición.
Ahora se utiliza la función fetch para esto de forma mas simple vecha las promesas.
El problema era que una vez que una petición salia no había forma de detenerla. Esto es importante en SPA donde el usuario puede salir de una página y así quedarse una llamada que estaba ocurriendo. Sería preferible detener la llamada asi ahorrar una bytes y mejorar el rendimiento de nuestra app.
AbortController que nos permite enviar una señal a una petición en plena ejecución para detenerla.

Bastante útil la clase

Esto se parece mucho a lo que aprendí en kotlin-android, se me hará más sencillo el aprendizaje 😄

Tuve problemas con el Scope de la variable controller, declarandola con let el stopButton no tenia acceso a ella, asi que la declare una sola vez con var y funcionó

Hola, les dejo la documentación de esta API del DOM. https://developer.mozilla.org/en-US/docs/Web/API/AbortController.

No hay mucho que ver, ya solo tiene el método abort que vimos en la clase. Pero ahí se encuentra un ejemplo, pienso que valdría la pena hecharle un ojo.

Si observan que en la parte de “Time” y “Waterfall” en Sources aparece como Pending y no hay actividad, o si les aparece en la consola que tienen un error de CORS (temas de seguridad), agreguen lo siguiente justo al lado de controller.signal poniendo una coma:

mode: "no-cors"

De esta manera, el tiempo y la barra se irán actualizando en tiempo real.


Atención:

Prohibido agregar esto en etapa de Producción. Sólo se usa por motivos de visualización en tiempo real por bloqueo de CORS.

Cancelar peticiones

Fetch aprovecha las promesas para pder realizar peticiones. El Problema es que fetch no podia cancelar las peticiones hasta ahora. En ocaciones es preferible detener una llamada para poder ahorrarnos espacio y hacer mas eficiente la aplicacion. Aqui llega AbortController. Permite dar una senal a una peticion FETCH para que se detenga.

Para esto en el FETCH neceistamos darle un objeto de configuracion donde le demos un URl ppondremos unos {} con un objeto de configuracion llamado Signal y esta vendra de un AbortController. Que nos dara los controles para detener la ejecucion. Esto se veria asi:

let controller = new AbortControler();
const response = await fetch(url, {signal: controller:signal});

Ahora si queremos detener, neceistamos llamar a nuestro:

controller.abort();

Fetch es un método de traer información desde un API por medio de promesas. Antiguamente no había forma de detener una promesa que ya fue enviada hasta que apareció Abort Controller.

Abort Controller permite enviar una señal a una petición fetch para que se detenga.


Para crear una url de un blob:

const imgUrl = URL.createObjectURL(blob)

Para detener la petición

const controller = new AbortController();

const response = await fetch(url, {signal: controller.signal});
const blob = await response.blob();
const imgUrl = URL.createObjectURL(blob);
img.src = imgUrl

// se le debe pasar el signal de controller al fetch
// para detener la petición:
controller.abort()

Cuando se cancele el fetch lanzará un error por lo que hay que manejarlo.

URL.createObjectUrl([blob])

  • This help us to create an object based on a blob format. (images, json, etc)
  • All the browsers have this feature to convert and use this.

interesante, siempre me pregunté como cancelar una petición echa usando fetch.

el primer encuentro con fetch fue dificil, pero cuando entiendes la sintaxis el uso que puedes hacer es muy bueno (Y)

Bunea expliacion de como cancelar una peticion o Fetch

Por si les interesa mi blogpost sobre fetch, axios y otras cosillas
fetch_axios_etc

Esto puede ser muy útil para la carga de las Single Page Applications 😮

Bendecido y afortunado por el internet

Los que no tenemos una conexión bende…
LOADING....

La peticiones AJAX permitieron en su tiempo hacer peticiones asíncronas al servidor sin tener que detener la carga de la página. Hoy en día se utiliza la función fetch para esto.

Alguien sabe porque no sirve en Opera? pero en Chrome si?

excelente clase cada momento aprendemos mucho más

Excelente clase, esto me parece genial y muy util para proyectos que manejan peticiones con consultas muy grandes al server!

¿Alguien se da idea de como hacer para poder volver a cargar la imagen, una vez que abortamos el fetch? Estuve buscándole la vuelta pero no la encuentro. Cuando quiero volver a fetchear me tira “The User Aborted a Request” en consola.

Puse el throttling en slow 3G y me cargo en el mismo tiempo 😩😩

😄

Alguien sabe donde hay una buena documentación de fetch? Solo encuentro la de Mozilla y no me queda del todo claro.

No entiendo porque al ultimo del onclick de loadbutton se llama la funcion de stopLoading();

👍 Super. Gracias

Genial, super genial

No se si alguno tuvo el mismo problema que yo y es que no me permite cancelar la petición ya que el botón se iba inmediatamente para ello encontré un solución muy breve y la comparto por si a alguien le sirve 😄.

Fue tan sencillo como usar la propiedad FileReader que básicamente lo que hace es que permite leer un fichero en este caso en formato .blob.
Para ello se creó el reader, a dicha instancia del FileReader con el método readAsDataURL se le pasa como parámetro el fichero y se espera con await para manejarlo como un evento asíncrono.
Hecho esto gracias al método onloadend que me permite pasarle una función que se va a ejecutar cuando termine la lectura del fichero ya puedo manejar ahí mi evento.

Excelente herramienta.

Muy util

Que clase tan buena, me encanto

Excelente me parece una funcionalidad genial

Hola a todos, disculpen, alguien me puede decir dónde sale la opción de network con toda la información que muestra el profe, en el navegador de Mozilla?

La API fetch proporciona una interfaz JS para acceder y manipular partes de las solicitudes HTTP, como solicitudes y respuestas. Este método fetch() también proporciona una lógica y fácil manera de obtener recursos de forma asíncrona a través de las redes.(source)

Gracias que buena explicaciones

Fetch

Las peticionas AJAX, fueron todo un hito en la web, puer nos permitieron cargar infromación sin tener que recargar toda la página. Para esto, se utiliza el método XMLHttpRequest, pero su implementación llega a ser un poco compleja en ciertos casos. Es por esto que llega la función fetch para simplificar nuestros requests, con la ventaja de que aprovecha las promesas. La única desventaja era que no había modo de cancelar una petición, lo cuál es muy importante en Single Page Applications, en donde puede que una respuesta asíncrona rompa flujos o sobrecargue datos innecesarios. Para ello llegó abortController. Consideremos este ejemplo, en el que queremos cargar una imagen muy pesada.

Consideremos las siguientes funciones asíncronas, que están preparadas para hacer el request de una imagen y asignarla a un elemento img de nuestro HTML, con la opción de abortar dicha petición:

startButton.onclick = async function() {
  startLoading()
  // intanciamos AbortController
  controller = new AbortController()
    try {
      // pasamos la señal del controller
    const response = await fetch(url, {signal: controller.signal})
    // extraemos el archivo binario de la respuesta
    const blob = await response.blob()
    // generamos una url para colocar al elemento img
    const imgUrl = URL.createObjectURL(blob)
    img.src = imgUrl
  } catch(error) {
    console.error(error.message)
  }
  stopLoading()
}
stopButton.onclick = async function() {
  // abortamos el fetch
  controller.abort()
  stopLoading()
}

Muy bueno!

Este video me oriento para entender archivos blob y su funcionamiento. Lo recomiendo.
https://www.youtube.com/watch?v=9Ih7ZIF5lpE&t=185s

aqui una imagen

Si quieren profundizar en el tema de las DevTools ya hay un curso de Platzi sobre eso: Curso de Debugging con Chrome DevTools

muy buen ejemplo.

Uhhh es bueno saber que se pueden cancelar, podría ser bueno usar esto en los hooks de destroy de componentes de Vue ^^

Las promesas ya tienen un try catch invisible, no es necesario usar la sentencia en explícito.
Otro dato, cualquier función asíncrona es una promesa.

El método fetch abrirá un canal de comunicación con un recurso externo (en red) devolviendo una promesa, por lo tanto se puede acceder a la respuesta mediante un then

El método fetch abrirá un canal de comunicación con un recurso externo (en red) devolviendo una promesa, por lo tanto se puede acceder a la respuesta mediante un then. Como todas las promesas se puede acceder a la respuesta dentro de funciones async, mediante al el uso de la palabra reservada await y de esta manera utilizar de manera más sencilla la respuesta. El fetch historicamente proviene del XMLHttpReques con un funcionamiento similar al JQUERY.ajax con un mejor manejo de los errores.

El método fetch abrirá un canal de comunicación con un recurso externo (en red) devolviendo una promesa, por lo tanto se puede acceder a la respuesta mediante un then. Como todas las promesas se puede acceder a la respuesta dentro de funciones async, mediante al el uso de la palabra reservada await y de esta manera utilizar de manera más sencilla la respuesta. fetch historicamente proviene del XMLHttpReques (o XHR para los cuates) con un funcionamiento similar al JQUERY.ajax (Asyncronous JavaScript And XML) con un mejor manejo de los errores (ya que fetch sólo fallará cuando hayan problemas de red, manejando los errores mediante Response.status, Response.statusText y Response.ok).

Muy buena explicación