Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a setTimeout to a fetch promise that uses redux?

After a certain amount of seconds if a fetch promise has not been resolved I want to show a timeout error to the user.

I've seen some good examples of adding a setTimeout to fetch here: https://github.com/github/fetch/issues/175

But how can I handle timing out a fetch promise that also uses redux? E.g.

export function getData() {
  return (dispatch, getState) => {
    fetch('blah.com/data')
    .then(response => response.json())
    .then(json => dispatch(getDataSuccess(json)))
    .catch(
      error => {
        console.log(error)
      }
    )
      dispatch({
        type: DATA_FETCH_REQUEST
      })
  }
}

Thanks for reading!

like image 430
Brien Crean Avatar asked Jul 21 '16 18:07

Brien Crean


People also ask

How to wrap setTimeout in a promise in JavaScript?

We can wrap setTimeout in a promise by using the then () method to return a Promise. The then () method takes upto two arguments that are callback functions for the success and failure conditions of the Promise. This function returns a promise. There can be two different values if the function called onFulfilled that’s mean promise is fulfilled.

How to timeout a fetch() request?

How to Timeout a fetch () Request 1 Default fetch () timeout#N#By default a fetch () request timeouts at the time indicated by the browser. In Chrome a... 2 Timeout a fetch () request#N#fetch () API by itself doesn’t allow canceling programmatically a request. To stop a... 3 Summary More ...

How does Redux handle data fetch?

Data fetching logic for Redux typically follows a predictable pattern: A "start" action is dispatched before the request, to indicate that the request is in progress. This may be used to track loading state to allow skipping duplicate requests or show loading indicators in the UI.

What is setTimeout function in JavaScript?

setTimeout is a javascript function that takes in another function or a random code snippet and executes it after a specified period of time (millisecond). The setTimeout function will execute the console.log () function after five seconds of running the code. Here, we can see that the setTimeout function can take in another function.


2 Answers

I've been dying to have a reason use Promise.race, it works perfectly for this use case. Promise.race waits for the first resolve or first reject. So if reject fires first then it will never fire the then on Promise.race. More here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race. Sorry, I didn't get a chance to test the code.

export function getData() {
  return (dispatch, getState) => {
    let timeout = new Promise((resolve, reject) => {
      setTimeout(reject, 300, 'request timed out');
    })
    let fetch = new Promise((resolve, reject) => {
      fetch('blah.com/data')
        .then(response => response.json())
        .then(json => resolve(json))
        .catch(reject)
    })
    return Promise
      .race([timeout, fetch])
      .then(json => dispatch(getDataSuccess(json)))
      .catch(err => dispatch(getDataTimeoutOrError(err)))
  }
}
like image 111
Andrew Axton Avatar answered Oct 30 '22 14:10

Andrew Axton


Based on the snippet from github you mentioned, you can probably do something like this:

function timeoutPromise(ms, promise) {
  return new Promise((resolve, reject) => {
    const timeoutId = setTimeout(() => {
      reject(new Error('Timeout'));
    }, ms);
    promise.then(
      (res) => {
        clearTimeout(timeoutId);
        resolve(res);
      },
      (err) => {
        clearTimeout(timeoutId);
        reject(err);
      }
    );
  })
}

export function getData() {
  return (dispatch, getState) => {
    dispatch({type: DATA_FETCH_REQUEST});

    timoutPromise(5000, fetch('blah.com/data'))
    .then(response => response.json())
    .then(json => dispatch(getDataSuccess(json)))
    .catch(
      error => {
        // Change this as necessary
        dispatch({type: DATA_FETCH_FAILED});
        console.log(error);
      }
    );
  }
}

If you want to show an information to the user that the request has failed, you might want to handle the action with the type DATA_FETCH_FAILED.

like image 35
amann Avatar answered Oct 30 '22 14:10

amann