5

New to javascript/react/node/axios. Not new to programming

Having issues trying to get timeout on axios working in a mobile react app.

I have a node server with API end point set to test; this will accept the request, throw an error and simply not respond.

Eg: throw new Error(“testing for timeout”)

The app is hanging and will not move on until I stop the node server where immediately the catch block is executed.

I can verify that the app made contact with server by having the server do a console.log("hello") before throwing the error

I’ve created a new react app by new folder, “react-native init”, creating a button on app.js to initiate the call. Relevant code:

const axios = require('axios')

const test1Press = async () => {

  console.log("test1 pressed")

  // obviously not the actual url in this stackoverflow post
  axios.defaults.baseURL = 'https://mynodeserver.com/api'

  console.log("pre call")

  try
  {
    await axios.post('/debug/throw', {timeout: 2000})
    console.log("post call passed")
  }
  catch (err)
  {
    console.log("post call failed")
  }
}

Console window shows Pre call; then hangs. When I stop node server the app logs immediately with "post call failed"

I have also tried:

axios.defaults.timeout = 2000

and using an axios instance like:

axinst = axios.create({
  baseURL: 'https://parcelscan-staging.ctilogistics.com/api',
  timeout: 2000
})

console.log("pre call")

try
{
  await axinst.post('/debug/throw')
  console.log("post call passed")
}
catch (err)
{
  console.log("post call failed")
}

I can’t see what I’m doing wrong.

EDIT:

On further research I found forum posts with similar issues; looks like axios timeout may not be reliable as of May 2020; and a year later now in June 2021 ?

Suggested solutions are canceltokens eg:

const source = CancelToken.source();
try {
    let response = null;
    setTimeout(() => {
        if (response === null) {
            source.cancel();
        }
    }, 2000);
        
    response = await axios.post('/url',null,
        {cancelToken: source.token});
    // success
} catch (error) {
// fail
}

Tested this and working

andrew
  • 956
  • 3
  • 17
  • 27

2 Answers2

4

With await axios.post('/debug/throw', {timeout: 2000}), actually you send the payload {timeout: 2000} to the server, not set the timeout to 2 seconds. See an example here.

I tested with another syntax of axios and it worked

const test1Press = async () => {

    console.log("test1 pressed")

    // obviously not the actual url in this stackoverflow post
    axios.defaults.baseURL = 'http://localhost:9000'

    console.log("pre call")
    console.log(new Date().toUTCString());
    try {
        await axios({
            method: 'post',
            url: '/',
            timeout: 2000 // only wait for 2s
        })
        console.log(new Date().toUTCString());
        console.log("post call passed")
    }
    catch (err) {
        console.log(new Date().toUTCString());
        console.log("post call failed")
    }
}

test1Press();

On the server-side, I wait for 5 seconds to have the timeout error on the client-side

const http = require('http');

const server = http.createServer(function (req, res) {
    setTimeout(function () {
        res.write('Hello World!');
        res.end();
    }, 5 * 1 * 1000); // after 5s
})
    .listen(9000);

Running the code above gives me the timeout error after 2 seconds

test1 pressed
pre call
Mon, 28 Jun 2021 09:01:54 GMT
Mon, 28 Jun 2021 09:01:56 GMT
post call failed

EDIT I tested to create the instance of axios, this gives me the same result:

const test1Press = async () => {

    console.log("test1 pressed")

    // obviously not the actual url in this stackoverflow post
    const instance = axios.create({
        baseURL: 'http://localhost:9000',
        timeout: 2000,
    });

    console.log("pre call")
    console.log(new Date().toUTCString());
    try {
        await instance.post('/');
        console.log(new Date().toUTCString());
        console.log("post call passed")
    }
    catch (err) {
        console.log(new Date().toUTCString());
        console.log("post call failed")
    }
}

test1Press();
Đăng Khoa Đinh
  • 3,605
  • 3
  • 10
  • 28
  • 1
    Your second example is the same as my last. I've changed my server code to match yours so it's now "sleeping" instead of throwing an error.. and still my app waits for 5 seconds and I don't get the 2 second failed catch block - with both versions. Hmmm. I don't think then this is a syntax issue; could be related to some sort of conflict with axios/react/other – andrew Jun 28 '21 at 10:54
  • I'm using https - ie url of https://myurl.com/api/debug/throw would https cause an issue with timeout ? – andrew Jun 28 '21 at 11:00
  • I don't think it's related to https/http. I didn't test with react, might be it's the difference. Can you do a test with only axios ? – Đăng Khoa Đinh Jun 28 '21 at 11:07
  • this is where my limited experience with react/javascript/axios comes into play :( we are committed heavily to a react solution but I could replace axios with another package; I might try that – andrew Jun 28 '21 at 11:10
  • This link does suggest that axios works well with react and supports timeouts..https://medium.com/enappd/how-to-make-api-calls-in-react-native-apps-eab083186611 – andrew Jun 28 '21 at 11:16
  • I think this should work with react. The object is just to isolate the problem :). I admitted that it's weird if we run the same code and the result is different. My axios version is 0.21.1 if it matters – Đăng Khoa Đinh Jun 28 '21 at 11:18
  • and this link shows there was issues with timeout in May 2020: https://github.com/axios/axios/issues/647 - this may not have been fixed yet; I may need to try the cancel token route – andrew Jun 28 '21 at 11:29
  • I appreciate the help you've given - if you want to include the canceltoken code as an alternate in your post I can mark as accepted ? – andrew Jun 28 '21 at 11:57
  • You found it, great research :) I don't think it needed because all information is now in your question :) – Đăng Khoa Đinh Jun 28 '21 at 14:56
0

Let's 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.

See original answer for solution

Hamza Waleed
  • 1,092
  • 7
  • 11
  • 1
    Link is a different issue. I can verify that a connection is made. So internet connection/IP Address/domain name are all ok; i've got the server logging that a request was made. So in this case the axios time out should work, but it's not – andrew Jun 28 '21 at 06:16