typescript

Typescript. Try call api again if got any errors


I have function that calls API and returns result based on response. But sometimes i could receive error or something else goes wrong. I want my code to try again until good response is received.

Example code:

for(let i = 0; i < someValues.length; i++) {
    await Test(someValues[i]);
}

async function Test(someValue: string): Promise<SomeObject | null> {
    try {
        const response: any = await someapi.call(someValue); // if got some error from api (connect etc.) then try again 
        if(response) {
            return response;
        }

        return null;
    }
    catch(err) {
        console.log(err);
        setTimeout(async () => {
            await Test(someValue);
        }, 100);
    }
}

Is this code will work? If first try will get api error, what would this loop above receive as response?

Also getting this error in Promise<SomeObject | null> :

Function lacks ending return statement and return type does not include 'undefined'

Solution

  • The problem is that you're not returning anything in your catch block, so the function is implicitly returning undefined. If you want a delay before retry (a good call) you'll need to manage it differently.

    Something like this would work:

    for(let i = 0; i < someValues.length; i++) {
        await Test(someValues[i]);
    }
    
    async function Test(someValue: string): Promise<SomeObject | null> {
        try {
            const response: any = await someapi.call(someValue); // if got some error from api (connect etc.) then try again 
            if(response) {
                return response;
            }
    
            return null;
        }
        catch(err) {
            console.log(err);
            return new Promise(resolve => setTimeout(async () => {
                resolve(await Test(someValue));
            }, 100));
        }
    }
    

    Alternatively, a slightly cleaner way you could do it is something like this in that block:

    // Wait 100ms
    await new Promise(resolve => setTimeout(resolve, 100));
    // Retry
    return await Test(someValue);
    

    And a warning, if the call fails, you're going to infinitely recurse. You probably want to track some kind of count of attempts so you can abort at some point.