I have an Axios GET
request that starts fetching an API when clicking a button. This request takes a long time (around a minute) and I would like to cancel it and start a new one when the button is clicked again.
Also, I would also like to be able to cancel the request if it is pending and I refresh the page.
I tried everything I found here on SO but nothing seems to work. I also read the Axios doc about cancelling : https://github.com/axios/axios#cancellation.
All this lead me there :
Updated code (see edit below)
const CancelToken = axios.CancelToken;
let cancel;
function App() {
useEffect(() => {
async function getPairs() {
try {
if (cancel) {
cancel();
}
const res = await axios.get('http://localhost:3000/binance/pairs?timeframe='+timeframe+'&strat='+strat, {
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
});
if (res.status === 200 || res.data.status === 'success') {
setPairs(res.data.pairs);
setReloadConfig(false);
}
}
catch (err) {
if (axios.isCancel(err)) {
console.log("cancelled");
} else {
throw err;
}
}
}
// reloadConfig is a React useState hook that is set to true when clicking a button
if (reloadConfig) {
getPairs();
}
}, [reloadConfig]);
}
export default App;
Note that reloadConfig
is a React useState
hook that is set to true when clicking a button, therefore triggering the useEffect
hook and the Axios request.
Problem is, if I click the button multiple times, no request is cancelled and a new one is created every time. I can see all the requests being treated in my terminal.
How can I cancel the last pending request and create a new one when clicking the button triggering the useEffect
?
Also, how can I cancel a pending request if I refresh the page ?
----- Edit -----
After twiking a bit with the code, I found out that placing cancelToken
and cancel
variables before the component function declaration made me move forward. Now, cancel
is not undefined
anymore and I get the cancelled
message from the catch
block :
catch (err) {
if (axios.isCancel(err)) {
console.log("cancelled");
}
}
If I console.log(cancel)
, it returns this :
ƒ cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
}
So it tells me cancellation was successful (if I understand correctly ?), but I can still see all the requests being logged in the backend terminal and still being processed. What's wrong with it ?
Thank you very much
----- Edit 2 -----
The solutions showed above all worked. The problem was a misunderstanding on my part : when I do a call to my API to fetch the results, the results are actually fetched by a library that itself fetches one URI per result, meaning that one call to my API makes multiple calls to another API via said library.
I can say the solutions showed above by the community worked because I tried them on a sandbox with a "normal" mock API. I think what happens in my case is that, the library I use with my API calls +200 URLs, so I guess one call was cancelled but not the other 199.
If anyone have a solution to cancel everything that would be great but I think that's more of a backend situation than frontend one at this point.
Thanks to everyone for your help and patience.