Timeout in async/await Timeout in async/await typescript typescript

Timeout in async/await


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.


Ok I found this way:

async function _doSomethingInSeries() {    const res1 = await callApi();    const res2 = await persistInDB(res1);    const res3 = await doHeavyComputation(res1);    return 'simle';}async function doSomethingInSeries(): Promise<any> {  let timeoutId;  const delay = new Promise(function(resolve, reject){    timeoutId = setTimeout(function(){      reject(new Error('timeout'));    }, 1000);  });  // overall timeout  return Promise.race([delay, _doSomethingInSeries()])    .then( (res) => {      clearTimeout(timeoutId);      return res;    });}

Anyone errors?

The things that smells a bit to me is that using Promises as asynchronicity strategy will send us to allocate too many object that some other strategy needs but this is off-topic.


Problem with @Bergi answer that doSomethingInSeries continues executing even if you already rejected the promise. It is much better to just cancel by timeout.

Here is support of cancellation:

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

But it is even better to pass cancellation token to each async function and use it there.

Here is implementation of cancellation:

let cancellationToken = {  cancelled: false,  cancel: function() {    this.cancelled = true;  },  throwIfCancelled: function() {    if (this.cancelled) throw new Error('Cancelled');  }}

You can wrap it as class if you want.

And finally usage:

doSomethingInSeries(cancellationToken);setTimeout(cancellationToken.cancel, 5000);

Keep in mind that task is not cancelled immediately, so continuation (awaiting, then or catch) is not called exactly after 5 secs. To guarantee that you can combine this and @Bergi approach.