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()
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 });
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;
}, []);
}
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.');
}
}
}
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);
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();
In this example, the function createWebSocketWithAbort()
creates the WebSocket using the AbortController
to control the WebSocket disponibility.
Top comments (0)