使用Fetch执行超时错误 - React Native

问题描述 投票:5回答:4

我有一个正在运行的用户登录功能。但是,我想为fetch合并一个超时错误。有没有办法设置一个5秒左右的计时器,以便在这样的时间后停止尝试获取?否则,我只是在网络错误一段时间后得到一个红色屏幕。

  _userLogin() { 
    var value = this.refs.form.getValue();
    if (value) { // if validation fails, value will be null
    if (!this.validateEmail(value.email)) {
      Alert.alert(
          "Enter a valid email",
        )
  } else {
      fetch("http://51.64.34.134:5000/api/login", {       
        method: "POST", 
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        timeout: 5000, 
        body: JSON.stringify({
          username: value.email, 
          password: value.password, 
        })
      })
      .then((response) => response.json())
      .then((responseData) => {
        if (responseData.status == "success") {
        this._onValueChange(STORAGE_KEY, responseData.data.token)
        Alert.alert(
          "Login Success!",
        )
        this.props.navigator.push({ name: 'StartScreen'})
        } else if (responseData.status == "error") {
        Alert.alert(
          "Login Error",
          responseData.message
        )
        }
      })
      .done();
    }
  }},    
react-native fetch
4个回答
2
投票

作为a timeout option isn't defined in the official spec yet,没有标准的处理方法。 There is an abort defined,你可以与你自己的超时和承诺一起使用。例如,见过herehere。我已经复制了示例代码,但还没有自己测试过。

// Rough implementation. Untested.
function timeout(ms, promise) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject(new Error("timeout"))
    }, ms)
    promise.then(resolve, reject)
  })
}

timeout(1000, fetch('/hello')).then(function(response) {
  // process response
}).catch(function(error) {
  // might be a timeout error
})

另一种选择是自己修改fetch.js模块以添加一个调用abort的超时,如here所示。


2
投票

这就是我要做的事情:(这是我用来在我的应用程序上进行所有调用的“通用”功能)

我创建了一个超时函数,除非之前被清除,否则将被触发,然后我清除服务器响应的超时

   const doFetch = (url, callback, data) => { 

    //... creating config obj here (not relevant for this answer)

  var wasServerTimeout = false;

  var timeout = setTimeout(() => {
    wasServerTimeout = true;
    alert('Time Out')
  } , 3000)


      fetch(HOST + url, config)
      .then((response) => { 

        timeout && clearTimeout(timeout); //If everything is ok, clear the timeout

    if(!wasServerTimeout){
        return response.json()
    } 
      })
      .then((response) => {  
              callback && callback( response.data || response ); 
         }).catch((err) => {

           timeout && clearTimeout(timeout); //If something goes wrong, clear the timeout

     if(!wasServerTimeout){
          //Error logic here
       }

         });
    }

1
投票

我通过使用2个promises之间的竞赛来解决这个问题,这个竞争是作为fetch的包装器编写的。在我的情况下,我希望返回json的请求,所以也添加了。也许有更好的解决方案,但这对我来说正常!

包装器返回一个promise,只要没有代码错误就会解析。您可以检查result.status中的“success”并从result.data中读取json数据。如果出现错误,您可以在result.data中读取确切的错误,并将其显示或记录在某处。这样你总能知道出了什么问题!

var yourFetchWrapperFunction = function(method, url, headers, body, timeout=5000){    
var timeoutPromise = new Promise(function(resolve,reject){
                        setTimeout(resolve, timeout, {status: 'error', code: 666, data: 'Verbinding met de cloud kon niet tot stand gebracht worden: Timeout.'});
                      });
    return Promise.race([timeoutPromise, fetch(connectionType + '://' + url, {method: method, headers: headers, body: body})]).then((result) => {
                        var Status = result.status;
                        return result.json().then(function(data){
                          if (Status === 200 || Status === 0) {
                            return {status: 'success', code: Status, data: data};
                          }
                          else {
                            return {status: 'error', code: Status, data: 'Error (' + data.status_code + '): ' + data.message};
                          }
                        },function (response) {
                          return {status: 'error', code: Status, data: 'json promise failed' + response};
                        }).catch((error) => {
                          return {status: 'error', code: 666, data: 'no json response'};
                        });
                      }, function(error){
                          return {status: 'error', code: 666, data: 'connection timed out'};
                      }).catch((error) => {
                          return {status: 'error', code: 666, data: 'connection timed out'};
                      });
}

1
投票

有一个名为react-native-fetch-polyfill的npm包。此程序包始终使用最后一个稳定的提取版本并实现超时。您还可以使用现代的javascript async / await sintax。这是一个例子:

从'react-native-fetch-polyfill'导入提取;

import fetch from 'react-native-fetch-polyfill';

async checkNetwork() {
    const url = `https://yoururl.org`;
    const requestInfo = {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      timeout: 2000  // here is the timeout
    }
    try {
      let data = await fetch(url, requestInfo);
      if (data.status == 200) {
        let json = await data.json();
        return json;
      } else {
        Alert.alert('Error','Error message')
      }
    } catch (e) {
         Alert.alert('Error','your timeout message')
    }
  }
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.