我有一个脚本应该尝试连接3次到服务器,如果失败导航用户到No Connection page
。
我不知道如何尝试连接3次,然后如果失败则将用户导航到No Connection page
。
如何使用我的代码来解决此问题。
这是我到目前为止的代码:
const fetchModule = require('fetch');
const frameModule = require('ui/frame');
let timeTrig;
const waitPeriod = 7000;
function checkServerStatus() {
if (timeTrig) {
clearTimeout(timeTrig);
timeTrig = null;
}
timeTrig = setTimeout(() => {
frameModule.topmost().navigate('./views/no-connection');
}, waitPeriod);
return fetchModule.fetch(`${randomUrl}auth/ping`)
.then((result) => {
clearTimeout(timeTrig);
if (result && result.ok) {
return true;
}
frameModule.topmost().navigate({
moduleName: views/no-connection,
transition: {
name: 'slide',
},
});
})
.catch(() => {
if (timeTrig) {
clearTimeout(timeTrig);
timeTrig = null;
}
frameModule.topmost().navigate({
moduleName: 'views/no-connection',
transition: {
name: 'slide',
},
});
});
}
感谢任何帮助。
答案 0 :(得分:3)
也许这样的东西就是你想要的 - 不确定你的代码的哪一部分应该被重试,但这可能会给你一些想法
const fetchModule = require('fetch');
const frameModule = require('ui/frame');
const waitPeriod = 7000;
// retry "cont" times or until the promise resolves
const retry = (cont, fn) => fn().catch(err => cont > 0 ? retry(cont - 1, fn) : Promise.reject(err));
// failure code - reason will be the last failure reason ('not ok' or 'timeout') - not that it is used in your code
const noConnection = reason => frameModule.topmost().navigate({
moduleName: 'views/no-connection',
transition: {
name: 'slide',
},
});
// lets race between (resolved or rejected) fetch and a rejected timeout
const doFetch = () => Promise.race([
fetchModule.fetch(`${randomUrl}auth/ping`).then(result => {
if (result && result.ok) {
return true;
}
return Promise.reject('not ok');
}),
// above can be written as
// fetchModule.fetch(`${randomUrl}auth/ping`).then(result => (result && result.ok) || Promise.reject('not ok')),
new Promise((resolve, reject) => setTimeout(reject, waitPeriod, 'timeout'))
]);
const checkServerStatus = () => {
retry(3, doFetch).catch(noConnection)
};
或者,这是相同的代码,只是组织不同。我认为更好:p
const fetchModule = require('fetch');
const frameModule = require('ui/frame');
const waitPeriod = 7000;
// retry "cont" times or until the promise resolves
const retry = (cont, fn) => fn().catch(err => cont > 0 ? retry(cont - 1, fn) : Promise.reject(err));
// reject after a given timeout
const delayedReject = (delay, reason) => new Promise((_, reject) => setTimeout(reject, delay, reason));
//
const doFetch = () => fetchModule.fetch(`${randomUrl}auth/ping`)
.then(result => (result && result.ok) || Promise.reject('not ok'));
const checkServerStatus = () => retry(3, () => Promise.race([doFetch(), delayedReject(waitPeriod, 'timeout')]))
.catch(reason => frameModule.topmost().navigate({
moduleName: 'views/no-connection',
transition: {
name: 'slide',
},
}));
答案 1 :(得分:1)
这"尝试n次然后失败"问题的类型经常出现,以http提取或网络套接字的形式出现,什么不是。我之前实际上已经实现了promise TryNTimes功能。
这是一个更有趣的版本,我认为非常优雅和可重复使用。
我们有几个实用程序函数来模仿获取请求和承诺排序。
以下bring
函数就像获取一样,有50%的解析概率。
bring = (url,i) => new Promise((v,x) => Math.random() > 0.50 ? v(`Data from ${url}`) : x(`Error @ promise # ${i}`))
接下来,我们设置一个大小为n bring
个函数的数组。
promises = (f,n) => Array(n).fill(f),
接下来,我们对递归bring
函数的promise进行递归排序。如果被调用的bring
函数返回的promise会解析,我们会返回该分辨率,但如果拒绝,那么我们继续执行数组中的下一个,直到不再剩下。显然,数组的大小是尝试计数。
var bring = (url,i) => new Promise((v,x) => Math.random() > 0.50 ? v(`Data from ${url}`) : x(`Error @ promise # ${i}`)),
promises = (f,n) => Array(n).fill(f),
tryProms = ([f,...fs], url, i = 1) => f(url,i).then(v => `${v} @ try # ${i}`,
e => (console.log(`Failed @ try #${i}`),
fs.length ? tryProms(fs,url,++i)
: `All ${i} tries are failed`));
tryProms(promises(bring,3),"http://www.someAPI/data").then(console.log, console.log);