Uso de AbortController como alternativa para eliminar detectores de eventos

La idea de una recuperación “abortable” cobró vida en 2017 cuando AbortController
se 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 AbortController
cancelar 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 addEventListener
ahora 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 AbortController
es 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 AbortController
depender de dos removeEventListener
instancias 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, addEventListener
acepta la signal
propiedad 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 addEventListener
acepta oficialmente una AbortSignal. Si bien otros navegadores importantes, incluidos Firefox y Safari, permiten AbortController
integrar su señal addEventListener
es 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