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.