Skip to content Skip to sidebar Skip to footer

While Loop Promise, Chain Promise

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 na

Solution 1:

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 resolvesconstretry = (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 codeconstnoConnection = reason => frameModule.topmost().navigate({
    moduleName: 'views/no-connection',
    transition: {
        name: 'slide',
    },
});

// lets race between (resolved or rejected) fetch and a rejected timeoutconstdoFetch = () => Promise.race([
    fetchModule.fetch(`${randomUrl}auth/ping`).then(result => {
        if (result && result.ok) {
            returntrue;
        }
        returnPromise.reject('not ok');
    }),
    // above can be written as// fetchModule.fetch(`${randomUrl}auth/ping`).then(result => (result && result.ok) || Promise.reject('not ok')),newPromise((resolve, reject) =>setTimeout(reject, waitPeriod, 'timeout'))
]);

constcheckServerStatus = () => {
    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 resolvesconstretry = (cont, fn) => fn().catch(err => cont > 0 ? retry(cont - 1, fn) : Promise.reject(err));
// reject after a given timeoutconstdelayedReject = (delay, reason) => newPromise((_, reject) =>setTimeout(reject, delay, reason));
//constdoFetch = () => fetchModule.fetch(`${randomUrl}auth/ping`)
.then(result => (result && result.ok) || Promise.reject('not ok'));

constcheckServerStatus = () => retry(3, () =>Promise.race([doFetch(), delayedReject(waitPeriod, 'timeout')]))
.catch(reason => frameModule.topmost().navigate({
    moduleName: 'views/no-connection',
    transition: {
        name: 'slide',
    },
}));

Solution 2:

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) =>newPromise((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.

varbring    = (url,i) => newPromise((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);

Post a Comment for "While Loop Promise, Chain Promise"