Uso de AbortController como alternativa para eliminar detectores de eventos

La idea de una recuperación “abortable” cobró vida en 2017 cuando AbortControllerse publicó. Eso nos brinda una manera de abandonar una solicitud de API iniciada fetch()(incluso varias llamadas) cuando queramos.

Aquí hay un ejemplo súper simple para AbortControllercancelar una fetch()solicitud:

const controller = new AbortController();const res = fetch('/', { signal: controller.signal });controller.abort();console.log(res); // = Promise(rejected): "DOMException: The user aborted a request"

Realmente puedes ver su valor cuando se usa para una interfaz moderna de setTimeout. De esta manera, hacer un tiempo de espera de recuperación después de, digamos, 10 segundos, es bastante sencillo:

function timeout(duration, signal) {  return new Promise((resolve, reject) = {    const handle = setTimeout(resolve, duration);    signal?.addEventListener('abort', e = {      clearTimeout(handle);      reject(new Error('aborted'));    });  });}// Usageconst controller = new AbortController();const promise = timeout(10000, controller.signal);controller.abort();console.log(promise); // = Promise(rejected): "Error: aborted"

Pero la gran noticia es que addEventListenerahora acepta una Señal de Aborto de Chrome 88. ¿Qué tiene de bueno eso? Se puede utilizar como alternativa de removeEventListener:

const controller = new AbortController();eventTarget.addEventListener('event-type', handler, { signal: controller.signal });controller.abort();

¿Qué es aún más genial que eso? Bueno, como AbortControlleres capaz de cancelar varias solicitudes cancelables a la vez, agiliza el proceso de eliminar varios oyentes de una sola vez. Ya lo encontré particularmente útil para arrastrar y soltar.

Así es como habría escrito un script de arrastrar y soltar sin AbortControllerdepender de dos removeEventListenerinstancias para borrar dos eventos diferentes:

// With removeEventListenerel.addEventListener('mousedown', e = {  if (e.buttons !== 1) return;  const onMousemove = e = {    if (e.buttons !== 1) return;    /* work */  }  const onMouseup = e = {    if (e.buttons  1) return;    window.removeEventListener('mousemove', onMousemove);    window.removeEventListener('mouseup', onMouseup);  }  window.addEventListener('mousemove', onMousemove);  window.addEventListener('mouseup', onMouseup); // Can’t use `once: true` here because we want to remove the event only when primary button is up});  

Con la última actualización, addEventListeneracepta la signalpropiedad como segundo argumento, lo que nos permite llamar abort()una vez para detener todos los detectores de eventos cuando ya no sean necesarios:

// With AbortControllerel.addEventListener('mousedown', e = {  if (e.buttons !== 1) return;  const controller = new AbortController();  window.addEventListener('mousemove', e = {    if (e.buttons !== 1) return;    /* work */  }, { signal: controller.signal });  window.addEventListener('mouseup', e = {    if (e.buttons  1) return;    controller.abort();  }, { signal: controller.signal });}); 

Nuevamente, Chrome 88 es actualmente el único lugar donde addEventListeneracepta oficialmente una AbortSignal. Si bien otros navegadores importantes, incluidos Firefox y Safari, permiten AbortControllerintegrar su señal addEventListeneres imposible en este momento… y no hay señales (juego de palabras) de que planeen trabajar en ello. Dicho esto, hay un polyfill disponible.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir