10

I'm sending queries to my server using native fetch from Google Chrome or Mozilla Firefox:

fetch(url, {
  method: 'POST',
  body: formData,
  credentials: 'include'
})

I set up a server to send a response after 3 minutes and realized that both browsers only wait 2 minutes. Firefox resend the request once more before failing.

Is there a way to define a timeout bigger than 2 minutes (say infinite)?

Cichelero
  • 321
  • 1
  • 3
  • 7
  • See https://stackoverflow.com/questions/46946380/fetch-api-request-timeout and https://github.com/whatwg/fetch/issues/20#issuecomment-323740783 – sideshowbarker May 22 '18 at 14:44
  • 2
    I understand @sideshowbarker but all these descriptions show how to reduce the timout. I cannot set 3 minutes timeout by hand if my fetch promise rejects after 2 minutes. – Cichelero May 22 '18 at 15:02

3 Answers3

2

As far as I read fetch()'s documentation on MDN, it does not have any way to specify a timeout.

You can use request or axios module if you are using nodejs. or you can use XMLHttpRequest (plain javascript in browser).

For more information HTTP request timeouts in JavaScript

Akshay Garg
  • 80
  • 1
  • 3
  • 1
    It seems to me XMLHttpRequest timeout works on FireFox you can set it to any value and if you don't the default is it will wait forever. Good, although I would prefer to use fetch(). BUT Chrome seems to always timeout in about 2 minutes no matter what I do . – Panu Logic Aug 11 '19 at 15:58
0

I resorted to

async function fetchJSON(url: string, data: any = {}, method: string = "POST"): Promise<any> {
    const start = new Date().getSeconds();
    const timeoutTimer = 10000
    
    while (new Date().getSeconds() - start < 10) {
        try {
            const res = await fetch(url, {
                method,
                headers: {
                    "Content-Type": "application/json; charset=utf-8"
                },
                body: JSON.stringify(data)
            });

            try {
                return await res.json();
            } catch (e) {
                if (res.status < 400) {
                    return res.status;
                } else {
                    throw e;
                }
            }
        } catch (e) {
            await new Promise((resolve) => {
                setTimeout(resolve, timeoutTimer);
            })
        }
    }
}

that is, the timeout is 10 seconds.

Vitor Ceolin
  • 196
  • 17
Polv
  • 1,918
  • 1
  • 20
  • 31
-1

To make the timeout "infinite" I use this:

fetch (serverUrl)
.then
( resp  => resp.json()
)
.then
( json => $cback (json)
)
.catch
( e    => $cback (e)
);

The '$cback' is an in-scope visible callback-function which detects if it's 1st argument is an instanceof Error. If so it will make a new call to fetch(). If it does NOT detect it is an error it uses the response for whatever it was intended, and then makes a new call to fetch.

This seems to work great on FireFox. The fetch does not timeout which is what I want. Unfortunately on Chrome fetch() ALWAYS times out in about 2 minutes That causes the catch-clause to fire, in other words the timeout is seen as an error. But I catch it.

The real problem for me on Chrome is that even though I catch the error it still produces an error-entry in the log about the no-response-request. So if users leave their browser open before going to lunch they will see many error-messages in their browser-log (if they care to look) and I'm afraid the number of errors there will cause them to "freak out".

Panu Logic
  • 2,193
  • 1
  • 17
  • 21