如何使用setTimeout中断React Native中的获取请求?

时间:2019-04-09 12:27:42

标签: react-native

我正在尝试通过获取请求从服务器获取一些数据。 有时网络会失败或发生类似的其他事情,我想超时以防止进一步的错误并获得更好的体验。

实际上,我想等待20秒,如果没有收到任何答复,我想显示错误并中断获取请求。

我有一个加载模式,可以通过超时关闭它,但是我也想破坏获取请求。

这是我的提取请求代码:

_testPress = async () => { 
        //setTimeout(() => {this.setState({loading: false})}, 20000)
        this.setState({loading : true})
        fetch(getInitUrl('loginUser'), {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({          
          password : this.state.password,
          email : this.state.emailAddress,            
        }),
      }).then(response => Promise.all([response.ok, response.status ,response.json()]))
      .then(([responseOk,responseStatus, body]) => {        
        if (responseOk) {
          //console.log(responseOk, body);
          this._signInAsync(body.token);
          // handle success case
        } else {
          console.log(responseStatus);
          this.setState({
            showAlert : true,
            alertType : true,
            alertMessage : body.message
          });
        }
      })
      .catch(error => {
        console.error(error);
        // catches error case and if fetch itself rejects
      });
      }

我使用setTimeout关闭加载模块,但它不会停止实际的请求,我希望它在20秒后停止。

请帮助我。 谢谢。

3 个答案:

答案 0 :(得分:1)

访存未实现连接超时。您也不能中止获取请求。

看看这个要点,它围绕着获取请求包裹了Promise.race。只要其中一个承诺(获取或超时)解决或拒绝,该承诺就会解决:
https://gist.github.com/davej/728b20518632d97eef1e5a13bf0d05c7

类似的事情应该起作用:

Promise.race([
  fetch(getInitUrl('loginUser'), *...fetchparams* ), 
  new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Timeout')), 7000)
  )
]).then(*stuff*).catch(*stuff*)

或者,您也可以尝试axios,这是fetch的替代方法,并支持超时: https://github.com/axios/axios

答案 1 :(得分:1)

没有可以添加到fetch的标准参数,但是您可以执行以下操作:

// creating a wrapper for promises
function timeout(milliseconds, promise) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error("timeout exceeded"))
    }, milliseconds)
    promise.then(resolve, reject)
  })
}

// using that wrapper with fetch
timeout(1000, fetch('/api'))
  .then(function(response) {
     // response success
}).catch(function(error) {
  // timeout error or server error
})

示例:

超时已超过:

// creating a wrapper for promises
function timeout(milliseconds, promise) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error("timeout exceeded"))
        }, milliseconds);

        promise.then(resolve, reject);
    });
}
  
const requestErr = new Promise((resolve, reject) => {
    setTimeout(() => {
        // request finished.
        resolve();
    }, 2500);
})

timeout(1000, requestErr)
    .then(function(response) {
        console.log("OK!");
    }).catch(function(error) {
        console.log("ERROR TIMEOUT!");
    });

未超过超时时间:

// creating a wrapper for promises
function timeout(milliseconds, promise) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error("timeout exceeded"))
        }, milliseconds);

        promise.then(resolve, reject);
    });
}

const requestOk = new Promise((resolve, reject) => {
    setTimeout(() => {
        // request finished.
        resolve();
    }, 500);
})

timeout(1000, requestOk)
    .then(function(response) {
        console.log("OK!");
    }).catch(function(error) {
        console.log("ERROR TIMEOUT!");
    });

您还可以使用具有自己的超时设置的AXIOS

答案 2 :(得分:0)

您可以通过在获取选项中传递“信号”来中止获取请求。

AbortSignal对象实例;允许您与获取请求进行通信,并根据需要通过AbortController中止该请求。

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

完整的代码示例在这里。

https://javascript.info/fetch-abort

let controller = new AbortController();
fetch(url, {
  signal: controller.signal
});

controller.abort();