How to use AbortController

How to use AbortController

Tags
Web Dev
Published
January 3, 2023
Author
Toan Ho

What is AbortController?

The AbortController interface represents a controller object that allows you to abort one or more Web requests as and when desired.
You can create a new AbortController object using the AbortController() constructor. Communicating with a DOM request is done using an AbortSignal object.

Why do we need to use AbortController?

For example, when users want to search for something on our web application.
The request will be like this:
  • Request 1 (R1): /search?q=kon
  • Request 2 (R2): /search?q=konvoy
  • Request 3 (R3): /search?q=konvoy+kegs
notion image
In the normal network, we expect responses to be returned in order. That means the R1 will complete first. Then comes R2 and R3.
But how about if there’s a problem from server, it makes R3 complete first, then R2, R1?
Take a look at the code below:
const [data, setData] = useState([]); setTimeout(async () => { try { if (keyword) { setLoading(true); const response = await searchSomething( { keyword: keyword, }, id ); setData(items); setLoading(false); } } catch (err) { console.error(err) } }, 300)
In case the R3 completed first, then R2, R1. The data will contain the result of R1, not R3. We surely don’t want it happen.
That why we will use AbortController

How to use AbortController?

Read the sample code below
class ApiOption { ... abort?: { key?: string; enabled?: boolean; }; } class ApiClient { private requests: Record<string, AbortController>; private async request( method: HttpMethods, endpoint: string, options?: ApiOption ) { // sample request key should be: GET/locations/search[order-form-w] const requestKey = `${method}${path}[${key || ''}]`; // check if abort flag is enabled or not if (enabled) { const previousRequest = this.requests[requestKey]; if (previousRequest) { // call this function to abort the previous request previousRequest.abort(); } } // init new AbortController const abortController = new AbortController(); // we will get the signal from AbortController instance const { signal } = abortController; this.requests[requestKey] = abortController; await fetch(endpoint, { signal: signal, ... }); ... } public async searchSomething() { return this.request('GET', '/xxx/...', { abort: { enabled: true } }); } }
 

Use Case

In most cases, we need to combine debounce input and AbortController together.
Follow the example below. You’ll see:
  • When the user typing kon → because we already applied to debounce input → only kon is sent to our server.
  • The user continues typing → the 2nd request with konvoy keyword has been called → because we already applied AbortController ⇒ the 1st request has been canceled
Using this way, we do not need to be concerned about the data. Only the latest data will be responded

Reference