I have a script that should try to connect 3 times to server if this fails navigate the user to the No Connection page
.
I don't know how to attempt a connection 3 times and then navigate user to the No Connection page
if this fails.
How can I use my code to achieve this problem.
Here is the code I have so far:
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',
},
});
});
}
Any help is appreciated.
Perhaps something like this is what you want - not exactly sure which part of your code should be retried, however this may give you some ideas
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)
};
Alternatively, this is the same code, just organised differently. I think better :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',
},
}));
This "try n times and then fail" type of questions are frequently appearing, let in the form of http fetches or web sockets and what not. I had actually implemented a promise TryNTimes functionality before.
Here is a more interesting version which i think is very elegant and reusable.
We have several utility functions just to mimic the fetch requests and promise sequencing.
The following bring
function is like fetch with 50% probability of resolving.
bring = (url,i) => new Promise((v,x) => Math.random() > 0.50 ? v(`Data from ${url}`) : x(`Error @ promise # ${i}`))
Next we set up an size n array of such bring
functions.
promises = (f,n) => Array(n).fill(f),
Next we sequence the promise returning bring
functions recursively. If the promise returned by the invoked bring
function resolves we return that resolution but if rejects then we carry on with the next one in the array up until there are no more left. Obviously the size of the array is the try count.
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);