如何将 setTimeout 添加到使用 redux 的获取承诺中?

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

如果在一定秒数后未解决获取承诺,我想向用户显示超时错误。

我在此处看到了一些添加 setTimeout 以获取的很好的示例: https://github.com/github/fetch/issues/175

但是我如何处理同样使用 redux 的 fetch promise 超时?例如

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

感谢阅读!

根据您提到的 github 中的代码片段,您可能可以这样做:

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

如果您想向用户显示请求失败的信息,您可能希望处理类型为 DATA_FETCH_FAILED 的操作。

我一直渴望有理由使用 Promise.race,它非常适合这个用例。 Promise.race 等待第一个解析或第一个拒绝。因此,如果 reject 首先触发,那么它永远不会在 Promise.race 上触发 then。更多信息 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race。抱歉,我没有机会测试代码。

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