node.js - Timeout em async/await
Estou com Node.js e TypeScript e estou usando async/await. Este é o meu caso de teste:
async function doSomethingInSeries() {
const res1 = await callApi();
const res2 = await persistInDB(res1);
const res3 = await doHeavyComputation(res1);
return 'simle';
}
Eu gostaria de definir um tempo limite para a função como um todo. Ou seja, se res1 leva 2 segundos, res2 leva 0,5 segundos, res3 leva 5 segundos, eu gostaria de ter um tempo limite que, após 3 segundos, me permitisse lançar um erro.
Com uma chamada normal de setTimeout é um problema porque o escopo é perdido:
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';
}
E eu não consigo capturá-lo com o Promise.catch normal:
doSomethingInSeries().catch(function(err) {
// errors in res1, res2, res3 will be catched here
// but the setTimeout thing is not!!
});
Alguma ideia de como resolver?
Resposta #1
Você pode usar Promise.race para criar um tempo limite:
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
})
Você não pode usar setTimeout sem envolvê-lo em uma promise.
Resposta #2
Ok, eu encontrei este caminho:
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;
});
}
Alguém cometeu erros?
As coisas que me deixam um pouco desconfiado é que usar Promises como estratégia de assincronidade nos levará a alocar muitos objetos que alguma outra estratégia precisaria, mas isso é fora do tópico.
