简体   繁体   中英

How to attempt an async function multiple times using promise, .then(), .catch()

I need to do several attempts on the async function getDBfileXHR , but I don't know how to handle this. I am new to chaining promises. Should I chain them like this?

return getDBfileXHR(dbUrl(), serverAttempts)
    .then(function () { // success
        console.log('-basic XHR request succeeded.');
        return dbReadyDeferred.promise;
    })
    .catch(function (){
        return getDBfileXHR(dbUrl(), serverAttempts)
        .then(function (){
            console.log('-basic XHR request succeeded after second attempt.');
            return dbReadyDeferred.promise;
        })
        .catch(function () { // error
            console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
            return fallbackToLocalDBfileOrLocalStorageDB();
        });
    })

or like that :

return getDBfileXHR(dbUrl(), serverAttempts)
.then(function () { // success
    console.log('-basic XHR request succeeded.');
    return dbReadyDeferred.promise;
})
.catch(function (){
    if (typeof serverAttempts !== "undefined") serverAttempts++;
    console.log('on passe dans le catch, serverAttempts = ', serverAttempts)
    if (serverAttempts < 2) {
        return getDBfileXHR(dbUrl(), serverAttempts)
        .then(function () { // success
            console.log('-basic XHR request succeeded.');
            return dbReadyDeferred.promise;
        })
        .catch(function (){
            console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
            return fallbackToLocalDBfileOrLocalStorageDB();
        })
    } else {
        console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
        return fallbackToLocalDBfileOrLocalStorageDB();
    }
})

This second code seems to work, but I am not sure it is best practices.

A simple and flexible solution involves creating a helper - benefit, reusable for anything that requires retrying promises:

var retryP = (fn, retry) => fn(retry).catch(err => (!isNaN(retry) && retry > 0) ? retryP(fn, retry - 1) : Promise.reject(err));

This generic function will retry fn for at most attempts number of times, passing 1 will retry once, ie make two attempts

your function can then be written:

var serverAttempts = 1; 
// this is should be the retry attempts, 
// so 0 is try at most once, 1 is at most twice etc

// argument n will be the number of retries "in hand", 
// so it counts down from the passed in value to 0
return retryP(n => getDBfileXHR(dbUrl(), serverAttempts - n), serverAttempts)        
    .then(() => {
        console.log('-basic XHR request succeeded after second attempt.');
        return dbReadyDeferred.promise;
    })
    .catch(() => {
        console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
        return fallbackToLocalDBfileOrLocalStorageDB();
    });

If you aren't comfortable with ES2015+ syntax
helper:

var retryP = function retryP(fn, retry) {
    return fn(retry).catch(function (err) {
        return !isNaN(retry) && retry > 0 ? retryP(fn, retry - 1) : Promise.reject(err);
    });
};

code:

var serverAttempts = 1;

return retryP(function (n) {
    return getDBfileXHR(dbUrl(), serverAttempts - n);
}, serverAttempts)
.then(function () {
    console.log('-basic XHR request succeeded after second attempt.');
    return dbReadyDeferred.promise;
})
.catch(function () {
    console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
    return fallbackToLocalDBfileOrLocalStorageDB();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM