← All writing
Craft · · 2 min

AbortController

One signal, one abort call, and every listener you attached with it goes away at once.

JavaScript Small Print

Everybody meets this as fetch cancellation.

listeners.js
const controller = new AbortController();
fetch(url, { signal: controller.signal });
controller.abort();
JavaScript

Which is useful, mostly for a search-as-you-type box where the response to the third keystroke can land after the response to the fourth and put stale results on screen.

The use I did not know about for years is that addEventListener takes the same signal.

listeners.js
const controller = new AbortController();
const { signal } = controller;
JavaScript
listeners.js
el.addEventListener('pointermove', onMove, { signal });
window.addEventListener('resize', onResize, { signal });
document.addEventListener('keydown', onKey, { signal });
JavaScript
listeners.js
controller.abort();
JavaScript

All three are gone. No keeping a reference to each handler, no matching removeEventListener calls with exactly the same function identity and exactly the same options object, which is the bug I have written more times than any other in this area. You pass an arrow function to both. The removal silently matches nothing and the listener lives forever.

It is particularly good for anything with a lifecycle: a drag that attaches three listeners on pointerdown and needs all of them gone on pointerup, a component teardown, a modal.

AbortSignal.timeout(5000) gives you a signal that aborts itself, which covers “give up after five seconds” without a setTimeout to manage alongside it.

Read similar posts
2 min

Intl.NumberFormat

Currency formatting is in the browser, has been for years, and is still being done with a hardcoded dollar sign and a call to toFixed in most of the code I read.

2 min

light-dark()

Two color values in one declaration, picked by the color scheme, which removes most of the reason a theme needed a second block of custom properties at all.