isomorphic-fetch icon indicating copy to clipboard operation
isomorphic-fetch copied to clipboard

any possible way to include timeout on fetch()?

Open ghost opened this issue 9 years ago • 18 comments

couldn't find the docs for this repository... my code looks like this:

fetch('/test', { method: 'POST', body: data })
    .then(function(response) {
        if (response.status >= 400) {
            throw new Error("Bad response from server");
        }
        return response.json();
})
    .then(function(response) {
        console.log(response)
    });

would like to fake a server response for the fetch... any ideas?

thanks in advance

ghost avatar Nov 22 '15 17:11 ghost

+1 not sure how to add timeout

anvk avatar Jan 15 '16 21:01 anvk

yes please, add a timeout option

Dindaleon avatar Jan 24 '16 20:01 Dindaleon

+1, please add timeout option

rahulbhanushali avatar Mar 25 '16 13:03 rahulbhanushali

you can do as fellow: `fetch("/test", { method: 'POST', body: data })

.then(function(response) {
    if (response.status >= 400) {
        const error = new error("Bad response from server")
        error.response = response
        error.message = "your error message,you can swith the status and set the message"
        throw error
    }
    return response.json();
}).then(function(response) {
    console.log(response)
}).catch(function(e) {
    if (!e.response) {
        e.message = "response time out!"
    }
    return Promise.reject(e);
})`

dbearscn avatar Apr 05 '16 15:04 dbearscn

This isn't handling a timeout for me...

There is an optional "timeout" property you can pass in the options.

fetch(url, {method: 'GET', timeout: 5000})
                .then(response => {
                    if (response.status >= 400) {
                        reject({
                            code: response.status,
                            message: response.statusText
                        });
                    } else {
                        resolve(response.json());
                    }
                })
                .catch(reject);
``

chrisdevwords avatar May 12 '16 17:05 chrisdevwords

Create a timeoutPromise wrapper...

function timeoutPromise(timeout, err, promise) {
  return new Promise(function(resolve,reject) {
    promise.then(resolve,reject);
    setTimeout(reject.bind(null,err), timeout);
  });
}

You can then wrap any promise...

timeoutPromise(100, new Error('Timed Out!'), fetcn(...))
  .then(...)
  .catch(...)

It won't actually cancel an underlying connection, but will allow you to timeout a promise.

tracker1 avatar May 12 '16 18:05 tracker1

When a client timeout occured, it's very important to cancel the http request. The fetch api will offer this functionality in a near future with the FetchController.

GabrielDelepine avatar May 16 '17 07:05 GabrielDelepine

By the way, I solved this neatly in react-native by using redux-saga.

raarts avatar Jul 04 '17 17:07 raarts

@raarts how redux-saga solve it? Can you post code in here?

ducpt2 avatar Feb 24 '18 03:02 ducpt2

Inside a saga, race the fetch call with a timeout like this:

  try {
    const { timeout, response } = yield race({
      timeout: call(delay, 10000),
      response: call(fetch, '<your endpoint>', { parms}),
    });
    if (timeout) {
      console.log('network timeout')
    } else {
      if (response.status === 200) {
        // success
      } else {
        // API error
      }
    }
  }
  catch(error) {
    // Other error by fetch
  }

raarts avatar Feb 24 '18 08:02 raarts

Kinda late here, this is based off of @tyler-canton code he posted up here

function fetch_timeout(url, options = {}) {
    /*
     * fetches a request like the normal fetch function 
     * but with a timeout argument added.
     */
    let timeout = options.timeout || 30000;
    let timeout_err = {
        ok: false,
        status: 408
    };
    return new Promise(function(resolve, reject) {
        fetch(url, options).then(resolve, reject);
        setTimeout(reject.bind(null, timeout_err), timeout);
    });
}

// use
fetch_timeout("http://google.com", {timeout: 500}).then(data => {
    // response here
}).catch(err => {
   // got an error, maybe timeout?
})

This lets you use fetch like how you would normally, but just have an added timeout option. Thanks @tyler-canton!

You might want to change the timeout_err to be an actual error you can check for, for my case this was perfect for what i needed to do.

kiorq avatar Mar 24 '18 17:03 kiorq

@kiorq I think you meant to do this:

fetch_timeout("http://google.com", {timeout: 500})

Rather than:

fetch("http://google.com", {timeout: 500})

Also your example doesn't help because all you do is a fetch. Something like the following would be beneficial:

fetchTimeout(copyOfUrl, {timeout: 3}) .then(data => console.log("Data: ", data)) .catch(reason => console.error("Caught error: ", reason.message));

In my case data came back immediately as undefined and I never get the error message after 3 seconds. Tried to fetch this large JSON file:

https://raw.githubusercontent.com/zemirco/sf-city-lots-json/master/citylots.json

JSONRice avatar Apr 10 '18 14:04 JSONRice

This is how you should be handling abort:

const controller = new AbortController()
const signal = controller.signal

setTimeout(() => { 
  controller.abort()
}, 1000)

fetch(url, { signal })

jimmywarting avatar Apr 11 '18 14:04 jimmywarting

For anyone else who gets hung up on Fetch not having timeout you could use the node-fetch rather than native Fetch API. In a lot of cases a timeout isn't necessary but it is necessary if you want to ensure TCP/IP connections close out and don't just have an open socket for some undetermined time. Here's what I ended up doing with node-fetch Works really well:

https://github.com/github/fetch/issues/617

JSONRice avatar Apr 11 '18 16:04 JSONRice

this should be in userLand

sibelius avatar Apr 19 '18 21:04 sibelius

If AbortController is not the solution for you, you can take a peek at this answer on stackoverflow (https://stackoverflow.com/questions/46946380/fetch-api-request-timeout). I found it quite useful !

Arrognz avatar Apr 30 '18 12:04 Arrognz

FWIW, I've opened an issue https://github.com/whatwg/fetch/issues/951 with a proposal for a timeout option that solves 90% of use cases, in case anyone's interested. I think it's super important to add to make sure calls to fetch (or res.json()) don't hang indefinitely.

ianstormtaylor avatar Oct 13 '19 15:10 ianstormtaylor

@ianstormtaylor You really made a number on every single repo that uses the fetch API. you should only have brought it up with whatwg and then the rest will follow.

jimmywarting avatar Oct 13 '19 16:10 jimmywarting