Productivity is the result of a commitment to excellence, intelligent planning, and focused effort.

Destroy event listeners with AbortController

Cover Image for Destroy event listeners with AbortController
George Crisan
George Crisan
Posted on:

The other day, I came across an unconventional usage for AbortController API. I was aware that AbortController can be used for better control over web requests, but I never thought to leverage it with event listeners.

The documentation for the API can be found at AbortController API webpage

I assume you know how to use the traditional EventTarget: removeEventListener() method so I will not talk about that, today we are talking about an alternative.

How it works?

The addEventListener() method can be configured with a signal object passed as a parameter. The signal object is generated by AbortSignal. The listener will be removed when the abort() method is invoked on the controller.

The signal object can be passed to as many event listeners as you like, or you could use multiple instances of AbortSignal for greater flexibility.

Example step by step

Let's have a look at an example. Initialise a controller instance and get hold of the signal object.

// Initialise a controller
const myController = new AbortController();

// Get hold of the signal object AbortSignal {}
const { signal } = myController;

Now let's set an event listener on the window, which will log to the console any key pressed. You can observe that our { signal } object has been passed to the method's second argument. This will give us control later on to abort as we need.

window.addEventListener('keyup', (event) => {
  console.log('Button has been pressed ', event.key);
}, { signal });

At this point every time you press a key on the keyboard it will get printed to the console.

Let's assume our application requires that this functionality to be available only 5 seconds (silly, but for the sake of the example should be fine.)

setTimeout(() => {
  // Remove all listeners that have received the signal generated by our controller.
  myController.abort();
}, 5000);

This approach has many benefits. You can have multiple controllers, or you can use a controller for multiple event listeners set, so each event listener set with the same signal object will be destroyed when the abort method is invoked.

The full code example is here:

// Initialise a controller
const myController = new AbortController();

// Get hold of the signal object AbortSignal {}
const { signal } = myController;

// Set event listener
window.addEventListener('keyup', (event) => {
  console.log('Button has been pressed: ', event.key);
}, { signal });


setTimeout(() => {
  // Remove all listeners that use this controller (via signal)
  myController.abort();
}, 5000);

Thank you and happy holidays!