我有一个正在运行的用户登录功能。但是,我想为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();
}
}},
作为a timeout option isn't defined in the official spec yet,没有标准的处理方法。 There is an abort defined,你可以与你自己的超时和承诺一起使用。例如,见过here和here。我已经复制了示例代码,但还没有自己测试过。
// 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所示。
这就是我要做的事情:(这是我用来在我的应用程序上进行所有调用的“通用”功能)
我创建了一个超时函数,除非之前被清除,否则将被触发,然后我清除服务器响应的超时
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
}
});
}
我通过使用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'};
});
}
有一个名为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')
}
}