Prerequisites
To clearly understand my article, I think you can take a look at the articles below:
After reading these articles, you may find their examples to be too simple and not applicable to real life. This is why I am writing this article. If you have any questions, please leave a comment.
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 instance, when users want to search for something on our web application.
The request will be as follows:
- Request 1 (R1):
/search?q=kon
- Request 2 (R2):
/search?q=konvoy
- Request 3 (R3):
/search?q=konvoy+kegs
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 what if there's a problem with the server? Should R3 be completed first, then R2, and finally 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)
If R3 completes first, followed by R2 and then R1, the data will contain the result of R1, not R3. We certainly want to avoid this situation.
That's why we will use
AbortController
.How to use AbortController?
Read the sample code below
class ApiOption { ... abort?: { key?: string; enabled?: boolean; }; } class ApiClient { // this is the key point I want to mention -> by saving the key + value // of abort controller, we easily trace them and cancel them 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 || ''}]`; // we also provide an option to check if abort flag is enabled or not if (enabled) { // because we've already store the abortController instance // -> we can get and cancel it 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; // we'll save the abortController instance 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 → onlykon
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 method, we do not need to be concerned about the data. Only the latest data will be returned.
Loading Comments...