DEV Community

Isaac "H3rmel" Reginato
Isaac "H3rmel" Reginato

Posted on

Using the full potential of AbortController

Today I want to talk about one of the most underrated JavaScript native APIs: The AbortController.

If you already know about it, you probably used it to deal with delayed requests in some React (or other front-end framework) application that uses Fetch API or Axios, right?

Here's the catch, the AbortController doesn't only works to cancel HTTP Requests, it works to cancel literraly everything!

So, in this post, I'm gonna show you the basics of AbortController, just in case you didn't know about it until now, and the examples to use it alongside Event Listeners, HTTP Requests, Streams and Third-party libraries.

Basics

Here's how you use it:

// Create a instance of it
const controller = new AbortController()

// The instance will return you this property
controller.signal
// And this method
controller.abort()
Enter fullscreen mode Exit fullscreen mode

The signal is a object instance of AbortSignal, is used to communicate with, or to abort, an asynchronous operation.

The abort() is a method to abort an asynchronous operation before it has completed.

Event Listeners

In event listeners, you can pass AbortController as a third parameter in the addEventListener() function:

const controller = new AbortController();

document.addEvenetListener("mousemove", doSomething(), { signal: controller.signal });
Enter fullscreen mode Exit fullscreen mode

Here is the example of AbortController with event listeners.

function setupEventListening() {
  const controller = new AbortController();
  const { signal } = controller; // You can deconstruct the instance if you want

  // Add multiple event listeners
  document.addEventListener('mousemove', handleMouseMove, { signal });
  document.addEventListener('keypress', handleKeyPress, { signal });
  window.addEventListener('resize', handleResize, { signal });

  // Function to remove all event listeners
  function cleanUp() {
    controller.abort();
  }

  return cleanUp;
}

// React Component example
function TrackingComponent() {
  useEffect(() => {
    const cleanUp = setupEventListening();
    return cleanUp;
  }, []);
}
Enter fullscreen mode Exit fullscreen mode

In this example, the function setupEventListening() sets up all the event listeners we need and returns the cleanUp() function that can be called to remove all event listeners when needed.

HTTP Requests

You can use the AbortController with Fetch API requests or even Axios requests.

In this example, I'll use axios:

import axios from 'axios';

async function fetchWithAxios() {
  const controller = new AbortController();

  try {
    const response = await axios.get('api/data', {
      signal: controller.signal
    });

    return response.data;
  } catch (error) {
    if (axios.isCancel(error)) {
      console.log('Request canceled.');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the AboutController is passed as a parameter in the config of the GET Request and is used in the finally block of the try/catch.

With this, if you do the same request more than one time, only the fastest request will be finished, the other that are delayed will be aborted when the fastest request gets done.

Stream

This is an example that creates an abstraction that uses AbortController to control the Stream availability.

async function processStreamData() {
  const controller = new AbortController();
  const { signal } = controller;

  const response = await fetch('api/stream', { signal });
  const reader = response.body.getReader();

  try {
    while (true) {
      const { done, value } = await reader.read();

      if (done) break;

      processChunk(value);
    }
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Stream process canceled.');
    }
    throw error;
  } finally {
    reader.releaseLock();
  }
}

// Cancel after 10s
const controller = new AbortController();
setTimeout(() => controller.abort(), 10000);
Enter fullscreen mode Exit fullscreen mode

Third-party Libraries

Here is an example using WebSockets, basically, you can create an abstraction that uses AbortController so you can close the connection when wanted.

function createWebSocketWithAbort(url) {
  const controller = new AbortController();
  const { signal } = controller;

  const ws = new WebSocket(url);

  signal.addEventListener('abort', () => {
    ws.close();
  });

  return {
    ws,
    controller
  };
}

const { ws, controller } = createWebSocketWithAbort('ws://example.com');

// Handlers Config
ws.onmessage = (event) => {
  console.log('Message received: ', event.data);
};

// Closes the WebSocket connection
controller.abort();
Enter fullscreen mode Exit fullscreen mode

In this example, the function createWebSocketWithAbort() creates the WebSocket using the AbortController to control the WebSocket disponibility.

References

Top comments (0)