Search code examples
node.jstypescripttimeoutpromiseasync-await

Timeout in async/await


I'm with Node.js and TypeScript and I'm using async/await. This is my test case:

async function doSomethingInSeries() {
    const res1 = await callApi();
    const res2 = await persistInDB(res1);
    const res3 = await doHeavyComputation(res1);
    return 'simle';
}

I'd like to set a timeout for the overall function. I.e. if res1 takes 2 seconds, res2 takes 0.5 seconds, res3 takes 5 seconds I'd like to have a timeout that after 3 seconds let me throw an error.

With a normal setTimeout call is a problem because the scope is lost:

async function doSomethingInSeries() {
    const timerId = setTimeout(function() {
        throw new Error('timeout');
    });

    const res1 = await callApi();
    const res2 = await persistInDB(res1);
    const res3 = await doHeavyComputation(res1);

    clearTimeout(timerId);

    return 'simle';
}

And I cannot catch it with normal Promise.catch:

doSomethingInSeries().catch(function(err) {
    // errors in res1, res2, res3 will be catched here
    // but the setTimeout thing is not!!
});

Any ideas on how to resolve?


Solution

  • You can use Promise.race to make a timeout:

    Promise.race([
        doSomethingInSeries(),
        new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 11.5e3))
    ]).catch(function(err) {
        // errors in res1, res2, res3 and the timeout will be caught here
    })
    

    You cannot use setTimeout without wrapping it in a promise.