isomorphic-fetch: any possible way to include timeout on fetch()?

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

About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Reactions: 23
  • Comments: 18

Most upvoted comments

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.

This is how you should be handling abort:

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

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

fetch(url, { signal })

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.

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

yes please, add a timeout option

+1, please add timeout option

+1 not sure how to add timeout

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.

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

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
  }

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

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.

@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

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