Exceções em cadeias de Promise em JavaScript
Suponha que, por algum motivo, nossa promise seja rejeitada com um erro:
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('error');
}, 3000);
});
Neste caso, a execução irá imediatamente para
o then que possui um tratador de erro,
ou para o primeiro catch, o que
aparecer primeiro.
Aqui está um exemplo da primeira situação:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
},
function(error) {
// a execução irá diretamente para aqui
}
).then(
function(result) {
console.log(result);
}
);
Aqui está um exemplo da segunda situação:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// a execução irá diretamente para aqui
}
).then(
function(result) {
console.log(result);
}
);
O tratador de erro tem duas opções de ação:
se ele conseguiu lidar com a situação excepcional,
pode retornar um resultado via return
e a execução continuará pela cadeia.
Se ele não conseguiu lidar com o erro, pode
ou não retornar nada, ou lançar uma exceção
via throw. Neste caso, a execução
passará para o próximo tratador de erro
(em then ou catch - o que vier
primeiro).
Geralmente, todos os erros da cadeia são capturados
em um único lugar: um catch é colocado
no final da cadeia:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// chegaremos aqui em caso de erro
}
);
Neste caso, a exceção pode originar-se na própria
promise, ou ser lançada via throw
em qualquer elo da cadeia:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
if (tudoBem) {
return result + '2';
} else {
throw new Error('erro'); // vamos para o tratador mais próximo
}
}
)
.then(
function(result) {
return result + '3';
}
).catch(
function(error) {
// o tratador mais próximo
}
);
Observe que o catch é necessário precisamente
para diagnosticar o erro: ele é solucionável ou não.
Se o erro for solucionável, o catch deve
passar sua solução para o then seguinte.
E se não for solucionável (ou se este catch
simplesmente não souber como resolvê-lo), devemos
ou não retornar nada ou lançar uma exceção:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
if (erroSolucionavel) {
return 'dados'; // enviamos para o próximo then
} else {
// não retornamos nada ou lançamos uma exceção
}
}
).then(
function(result) {
// aqui resolvemos o erro
}
);