Issue
I'm trying to abort any/all previous Axios requests, using AbortController(): https://axios-http.com/docs/cancellation
FAILS: In my testing, previous queries do not get aborted.
The search experience still works as expected, but every request gets fully digested when user slams away on filters. Instead I want all previous requests to just be aborted.
I want to avoid building logic that uses storing/tracking requests, tokens and/or promises. I'm familiar with this stuff and could build it, but just want to avoid all that.
Is the Axios' AbortController intended for this purpose?
UPDATE (WORKS): Thx to @Oluwafemi, my setup is working.
Two things had to be changed:
- Set a new instance of AbortController() directly after the abort.
- The signal needs to be a third parameter going into the Axios function, and not part of the payload (unlike what you see in material online).
Side note: In addition, not included here is a debouncer wrapping my query function (in my app), which alongside this AbortController, makes for a good multi-layer management of outgoing/incoming comms with the API server.
(I redacted a bunch of methods/lines that aren't relevant)
export default class MySearch {
constructor() {
// ONE-TIME SETUP
this.payload = null
this.active = {
q: "", // (Query) string e.g. "apples"
facets: {}, // Objects, each with array of options e.g. { 'size': [ '2 x 2 in', '3 x 3 in' ]}, { 'artists': [ 'mike', 'john', 'jane' ] }
page: null, // number e.g. 3
sortBy: null // string, one of: "default" | "newest" | "price_asc" | "price_desc"
}
// Declaring this here. Good/bad?
this.AxiosSearchController = new AbortController()
}
async query() {
return new Promise( async (resolve, reject) => {
// Abort any previous Axios request
this.AxiosSearchController.abort()
// Reinstantiate another instance of AbortController()
this.AxiosSearchController = new AbortController()
this.transformURL()
let requestParams = {
"page": this.active.page,
"sortBy": this.active.sortBy,
"filter": this.active.facets,
}
// Here we tell Axios to associate the request with the controller.
let AxiosSignal = {
signal: this.AxiosSearchController.signal
}
axios.post('/api/search/' + this.active.q, requestParams, AxiosSignal)
.then( response => {
this.payload = response.data
return resolve(response)
})
.catch( error => {
console.error(error)
return reject(error)
})
})
}
}
Solution
Where AxiosSearchController
is initialized for MySearch
depends on if you want multiple instances of the MySearch
to keep the same state of search or to maintain their own state of search.
When initialized in the constructor, each instance of MySearch
has its own state of search like you have in your snippet.
1. Instance 1 initialized
2. Instance 2 initialized
3. Instance 3 initialized
4. Instance 1 performs request
5. Instance 2 performs request
6. Instance 3 performs request
7. Instance 1 aborts request
8. Instance 2 continues request till fulfillment
9. Instance 3 continues request till fulfillment
When initialized outside of the constructor, all instances of MySearch
keep the same state of search.
1. Instance 1 initialized
2. Instance 2 initialized
3. Instance 3 initialized
4. Instance 1 performs request
5. Instance 2 performs request
6. Instance 1 has request aborted
7. Instance 3 performs request
8. Instance 2 has request aborted
Providing the signal property in the params argument is the proper format to set signal for the request for the axios
library.
However, when aborting any previous request, AxiosSearchController.signal.aborted
gets set to true
.
Without resetting this state of the abort controller, you shouldn't be able to make any further requests after the signal is aborted the first time.
You need to initialize AxiosSearchController after aborting request for the previous search.
this.AxiosSearchController.abort();
this.AxiosSearchController = new AbortController();
Answered By - Oluwafemi Sule Answer Checked By - Dawn Plyler (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.