Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

any possible way to include timeout on fetch()? #48

Open
ghost opened this issue Nov 22, 2015 · 18 comments
Open

any possible way to include timeout on fetch()? #48

ghost opened this issue Nov 22, 2015 · 18 comments

Comments

@ghost
Copy link

ghost commented Nov 22, 2015

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

@anvk
Copy link

anvk commented Jan 15, 2016

+1 not sure how to add timeout

@Dindaleon
Copy link

yes please, add a timeout option

@rahulbhanushali
Copy link

+1, please add timeout option

@dbearscn
Copy link

dbearscn commented Apr 5, 2016

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);
})`

@chrisdevwords
Copy link

chrisdevwords commented May 12, 2016

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);
``

@tracker1
Copy link

tracker1 commented May 12, 2016

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.

@GabrielDelepine
Copy link

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.

@raarts
Copy link

raarts commented Jul 4, 2017

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

@ducpt2
Copy link

ducpt2 commented Feb 24, 2018

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

@raarts
Copy link

raarts commented Feb 24, 2018

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
  }

@kiorq
Copy link

kiorq commented Mar 24, 2018

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.

@JSONRice
Copy link

JSONRice commented Apr 10, 2018

@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

@jimmywarting
Copy link

jimmywarting commented Apr 11, 2018

This is how you should be handling abort:

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

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

fetch(url, { signal })

@JSONRice
Copy link

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:

JakeChampion/fetch#617

@sibelius
Copy link

this should be in userLand

@Arrognz
Copy link

Arrognz commented Apr 30, 2018

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 !

@ianstormtaylor
Copy link

FWIW, I've opened an issue whatwg/fetch#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.

@jimmywarting
Copy link

jimmywarting commented Oct 13, 2019

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests