Reputation: 5755
I have set axios.defaults.timeout = 1000;
I stopped the server that provides me with the APIs.
But it takes more than 1s to timeout after sending a request.
This is how my request looks:
import axios from 'axios';
axios.defaults.timeout = 1000;
return axios.post(`${ROOT_URL}/login/${role}`, creds).then((response) => {
console.log(response);
if(response.status === 200) {
// If login was successful, set the token in local storage
localStorage.setItem(`${role}_log_toks`, JSON.stringify(response.data));
// Dispatch the success action
dispatch(receiveLogin(response.data));
return response;
}
}).catch(err => {
console.log(err);
// If there was a problem, we want to
// dispatch the error condition
if(err.data && err.status === 404) {
dispatch(loginError(err.data));
} else {
dispatch(loginError('Please check your network connection and try again.'));
}
return err;
});
I have also tried:
return axios.post(`${ROOT_URL}/login/${role}`, creds, {timeout: 1000}).then...
Axios doesn't stop fetching and after 5 - 10 minutes it finally shows network error. I understand that there are other techniques to handle timeout but why doesn't the timeout feature in axios work? What could be the reason that axios doesn't stop fetching?
EDIT: As mentioned in the comments, I have also tried:
import axios from 'axios';
const httpClient = axios.create();
httpClient.defaults.timeout = 500;
return httpClient.post(`${ROOT_URL}/login/${role}`, creds)
.then(handleResponse)
Upvotes: 88
Views: 251391
Reputation: 1145
The easiest way to achieve this if you are on nodejs17.3+
is as follows.
await axios({
method: 'post',
url: url,
headers: headers,
data: payload,
signal: AbortSignal.timeout(3000), // this will handle connection timeout. After waiting for 3000ms an exception will be thrown
timeout: 5000, // This one handles ONLY response timeout
})
Reference: Official documentation
Upvotes: 1
Reputation: 6413
From this axios issue (Thanks to zhuyifan2013 for giving the solution), I've found that axios timeout
is response timeout not connection timeout.
Let say you've requested the URL through axios and server is taking long time to respond, in this case the axios timeout will work.
But you don't have internet connection or the IP address or domain name that you're requesting not there, in this case axios timeout will not work.
You have to use one of the axios cancellation methods - cancelToken
example:
const source = CancelToken.source();
const timeout = setTimeout(() => {
source.cancel();
// Timeout Logic
}, 10000);
axios.get(ip + '/config', {cancelToken: source.token}).then((result) => {
// Clear The Timeout
clearTimeout(timeout);
// Handle your response
});
Please note that if you've valid connection, still the Timeout Logic block will get executed. So you've to clear the timeout
.
Upvotes: 117
Reputation: 41
Here's an example for specifying a timeout requestTimeout
in case of network error—in this case using async
/await
.
(Adapted from this answer for Fetch timeout)
import axios from 'axios';
const requestTimeout = 2000; // how long to wait in case axios never connects
axios.defaults.timeout = 1000; // how long axios should wait for a response
async function axiosWithTimeout (options) {
let reqTimeout; // make request timeout object available to both try and catch blocks
try {
const controller = new AbortController();
const signal = controller.signal;
reqTimeout = setTimeout(() => controller.abort(), requestTimeout);
const response = await axios({ signal, ...options });
clearTimeout(reqTimeout); // we have an response, clear timeout
return response;
} catch (error) {
clearTimeout(reqTimeout); // we have an error, clear timeout
return error;
}
}
axiosWithTimeout({
// method, url, headers, params, etc for axios request
});
Upvotes: 0
Reputation: 615
You might also need a newer version of Node. Timeouts were fixed in 14.14.0: https://github.com/nodejs/node/pull/34913
Upvotes: 0
Reputation: 634
Shoutout to @arthankamal because his answer is the solution and this is just an update and follow-up.
The CancelToken is deprecated from v0.22.0, because they switched to AbortController, so I updated his code. See more here: https://axios-http.com/docs/cancellation
TrySending(data) {
let abortController = new AbortController()
const timeout = setTimeout(() => {
abortController.abort()
console.log("Aborted")
}, 3000)
return axios
.post(
apiURL,
data,
{ signal: abortController.signal }
)
.then(response => {
clearTimeout(timeout)
return true
})
.catch(error => false)
}
This will return if it was succeeded or not.
Some notes:
{ message: 'canceled' }
Upvotes: 13
Reputation: 1947
submitHashtag = async () => {
const data = await axios.post('/pwa/basics.php', {
withCredentials: true,// if user login
timeout: 30000
})
if (!data) {
// action here
alert('reload window')
return
}
}
Upvotes: 9
Reputation: 2536
This code works for me:
axios({
method: "post",
url: 'http://example.com/api',
timeout: 1000 * 5, // Wait for 5 seconds
headers: {
"Content-Type": "application/json"
},
data: {
id: 1234
}
})
.then(response => {
const serverResponse = response.data;
// do sth ...
})
.catch(error => {
console.log(error);
});
If server won't respond in 5 seconds, it goes into catch block.
This is also useful: #1503
Upvotes: 41
Reputation: 7550
You need to create an instance of the axios http client:
const httpClient = axios.create();
httpClient.defaults.timeout = 500;
You can then use the httpClient as follows:
return httpClient.post(`${ROOT_URL}/login/${role}`, creds)
.then(handleResponse)
On a side note you can also set the base url in the same config instead of using ${ROOT_URL}
:
httpClient.defaults.baseURL = ROOT_URL
Upvotes: 25