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

Ars*_* S. 8 fetch react-native

我有一个正在运行的用户登录功能.但是,我想为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();
    }
  }},    
Run Code Online (Sandbox Code Playgroud)

Fan*_*Bao 9

// Wrapper function for fetch
const fetchSomething = async () => {
    let controller = new AbortController()
    setTimeout(() => controller.abort(), 3000);  // abort after 3 seconds
    const resp = await fetch('some url', {signal: controller.signal});
    const json = await resp.json();
    if (!resp.ok) {
        throw new Error(`HTTP error! status: ${resp.status}`);
    }
    return json;
}


// usage
try {
    let jsonResp = await fetchSomthing();
    console.log(jsonResp);
} catch (error) {
    if (error.name === 'AbortError') {
        console.log('Network Error');
    } else {
        console.log(error.message);
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为使用AbortController是中止呼叫的推荐方法fetch。上面的代码片段处理以下场景:

  1. 如果网络良好但 HTTP 返回错误状态,则会记录消息“HTTP 错误!...”。
  2. 如果网络出现故障,setTimeout将在三秒后AbortController触发中止。fetch将记录“网络错误”消息。
  3. 如果网络良好且 HTTP 响应良好,则将记录响应 JSON。

AbortController使用中止的文档fetch这里


Cas*_*rin 7

我制作了一个 ES6 函数,将 ES fetch 包装成一个 promise,这里是:

export async function fetchWithTimeout(url, options, timeout = 5000) {
    return Promise.race([
        fetch(url, options),
        new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout))
    ]);
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它:

const requestInfo = {
    method,
    headers,
    body,
};
const url = 'http://yoururl.edu.br'
let data = await fetchWithTimeout(url, requestInfo, 3000);
Run Code Online (Sandbox Code Playgroud)


Mic*_*eng 3

没有标准的方法来处理这个问题,因为官方规范中尚未定义超时选项定义了一个中止,您可以将其与您自己的超时和承诺结合使用。例如,如此此处所示。我已经复制了示例代码,但尚未亲自测试。

// 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
})
Run Code Online (Sandbox Code Playgroud)

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