我有一个正在运行的用户登录功能。但是,我想为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();
}
}},
答案 0 :(得分:2)
没有标准的方法来处理a timeout option isn't defined in the official spec yet。 There is an abort defined您可以将自己的超时和Promise结合使用。例如,见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所示。
答案 1 :(得分: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
}
});
}
答案 2 :(得分: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'};
});
}
答案 3 :(得分:1)
有一个npm软件包,称为react-native-fetch-polyfill。该程序包始终使用最后一个稳定的访存版本并实现超时。您还可以使用现代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')
}
}
答案 4 :(得分:0)
我可能迟到了,但是我编写了一个代码,该代码可以100%地使用提取超时API请求。
<?xml version="1.0" encoding="utf-8"?>
<nav modified="2019-05-29T06:10:36-07:00"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="navSrc.xsd">
<items>
<item id="100" appcode="My Accounts" href="launchapp?
appcode=My+Accounts" onclick="" target="" disabled="false" label="My
Accounts" locked="true" editable="true"/>
<item id="3000" appcode="Move Money" href="#" label="Move Money"
locked="false" editable="true"/>
</items>
</nav>
您只需要将 <?xml version="1.0" encoding="UTF-8"?>
<nav xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" modified="2019-05-29T06:10:36-07:00" xsi:noNamespaceSchemaLocation="navSrc.xsd">
<items>
<item appcode="My Accounts" disabled="false" editable="true" href="launchapp?appcode=My+Accounts" id="100" label="My Accounts" locked="true" onclick="" target=""/>
<item appcode="Move Money" editable="true" href="#" id="3000" label="Move Money" locked="false"/>
</items>
</nav>
传递给url,并将fetch_timeout(url, options) {
let timeout = 1000;
let timeout_err = {
ok: false,
status: 408
};
return new Promise(function (resolve, reject) {
fetch(url, options).then(resolve, reject).catch(() => {
alert('timeout.')
});
setTimeout(reject.bind(null, timeout_err), timeout);
});
}
传递给api-endpoint
参数。
答案 5 :(得分:0)
// 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);
}
}
我认为使用AbortController
是终止fetch
呼叫的推荐方法。上面的代码段处理以下情况:
setTimeout
将在三秒钟后触发AbortController
中止fetch
。消息“网络错误”将被记录。使用AbortController
中止fetch
的文档是here。