85

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?

Axios version 0.9.1

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)
shet_tayyy
  • 5,366
  • 11
  • 44
  • 82

7 Answers7

110

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.

PotatoFarmer
  • 2,755
  • 2
  • 16
  • 26
arthankamal
  • 6,341
  • 4
  • 36
  • 51
  • 1
    I want to add if you are having this issue with Angular, you can just add `.pipe(timeout(TIMEOUT_MILLIS))` to the observable. – andrewgazelka Sep 15 '20 at 20:32
  • axios uses XMLHttpRequest for browser env, and in case of > But you don't have internet connection - it will be a net::ERR_INTERNET_DISCONNECTED, so I think there is no real need to use axios (or any other) timeouts. It's applicable only on nodejs env. All other things browser can do. So if you really want to set a connection timeout, you can try to get a request object from axios and check for readyState - until it opened (1) - it's not connected yet. – Mikhail Shemenyov Feb 15 '21 at 11:51
  • 4
    I don't understand why they don't just implement this in the library rather than give us a broken timeout option. They just closed the issue without fixing it... – pguardiario Feb 28 '21 at 03:49
  • If the server is closed, will the axios timeout work – Irfan wani Jun 27 '21 at 03:40
  • 2
    I appreciate the thorough answer from @arthankamal. Would another alternative just be `Promise.race(axios.get(...), setTimeout(() => {}, 3000))` ? You could include a timeout in the axios request also to catch response timeouts separate from connection timeouts. – Tee Oct 20 '22 at 04:06
39

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

Ali Radmanesh
  • 2,248
  • 22
  • 26
25

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
Clarkie
  • 7,490
  • 9
  • 39
  • 53
  • 2
    1. I think you wanna return httpClient.post(`${ROOT_URL}/login/${role}`, creds) 2. Tried this as well. Didn't work. 3. Currently, I am using a technique mentioned by mislav here: https://github.com/github/fetch/issues/175 Works like a charm but I wanted the timeout provided by axios to work. – shet_tayyy Apr 19 '16 at 05:55
  • I'm not sure why that isn't working for you. What version of `axios` are you using? Can you include your `require` / `import` statements and axios initialisation code above? – Clarkie Apr 19 '16 at 06:13
12

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:

  • Isn't worth trying using the .finally because it won't work
  • If it was canceled it will go straight to .catch() and the error will be { message: 'canceled' }
Domotor Zsolt
  • 586
  • 5
  • 10
9
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
  }
 }
Zoe
  • 27,060
  • 21
  • 118
  • 148
Naved Khan
  • 1,699
  • 16
  • 13
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/22897810) – Daniel Cottone May 01 '19 at 10:46
  • @DanielCottone please review more carefully. This is also an answer – Zoe May 01 '19 at 10:57
  • It works but when I set timeout: 999999 an error: "net::ERR_CONNECTION_REFUSED" occurs rather than "timeout of 999999ms exceeded" when I set timeout greater than 5000 – JillAndMe Apr 01 '20 at 01:53
0

You might also need a newer version of Node. Timeouts were fixed in 14.14.0: https://github.com/nodejs/node/pull/34913

Brian
  • 563
  • 1
  • 5
  • 15
0

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
});
paulrw
  • 41
  • 1
  • 5