Sunday, 2 August 2020

Retry Async Function

The other day I had an async function that could fail (rejecting its promise) quite often and wanted to retry it a few times if needed. In the end I wanted to generate a new function with the retry functionality in it. I had done this in the past with pure promises and had been a bit more complex (it was something along the lines of what you can find here), but with async-await the code is so simple that I'm not sure why I'm posting it here, anyway:

 

//wrap setTimeout with an async-await friendly function
function sleep(ms){
    console.log("sleep starts");
    let resolveFn;
    let pr = new Promise(res => resolveFn = res);
    setTimeout(() => {
        console.log("sleep ends");
        resolveFn();
    }, ms);
    return pr;
}

//fn: function returning a Promise
//if the Promise is rejected we'll retry up to "attempts" times, with a "timeout" in between
//returns a new function with retry logic
function addRetryToAsyncFn(fn, attempts, timeout){
    return async (...args) => {
        while (attempts--){
            try{
                return await fn(...args);
            }
            catch(ex){
                console.log("attempt failed");
                if (!attempts)
                    throw ex;
            }
            await sleep(timeout);
        }
    };
}

//given an async function: getAndFormatNextTicket
//we'll use it like this:
let formattedTicket = await addRetryToAsyncFn(getAndFormatNextTicket, 5, 1000)("Francois");

Thanks to async/await the retry code for an async function is basically the same as the one for a normal function:

 

function addRetry(fn, attempts){
    return (...args) => {
        while (attempts--){
            try{
                return fn(...args);
            }
            catch(ex){
                console.log("attempt failed");
                if (!attempts)
                    throw ex;
            }
        }
    };
}

You can see a full example here.

No comments:

Post a Comment