Então, basicamente você está perguntando qual é a diferença entre esses dois (onde p
está uma promessa criada a partir de algum código anterior):
return p.then(...).catch(...);
e
return p.catch(...).then(...);
Existem diferenças quando p resolve ou rejeita, mas se essas diferenças importam ou não depende do que o código dentro dos manipuladores .then()
ou .catch()
faz.
O que acontece quando p
resolve:
No primeiro esquema, quando p
resolve, o .then()
manipulador é chamado. Se esse .then()
manipulador retornar um valor ou outra promessa que eventualmente seja resolvida, o .catch()
manipulador será ignorado. Mas, se o .then()
manipulador lança ou retorna uma promessa que eventualmente rejeita, então o .catch()
manipulador executará para uma rejeição na promessa original p
, mas também para um erro que ocorre no .then()
manipulador.
No segundo esquema, quando p
resolve, o .then()
manipulador é chamado. Se esse .then()
manipulador lança ou retorna uma promessa que eventualmente rejeita, então o .catch()
manipulador não pode capturar isso porque está antes dele na cadeia.
Então, essa é a diferença # 1. Se o .catch()
manipulador for AFTER, ele também poderá detectar erros dentro do .then()
manipulador.
O que acontece quando p
rejeita:
Agora, no primeiro esquema, se a promessa for p
rejeitada, o .then()
manipulador será ignorado e o .catch()
manipulador será chamado conforme o esperado. O que você faz no .catch()
manipulador determina o que é retornado como o resultado final. Se você apenas retornar um valor do .catch()
manipulador ou retornar uma promessa que eventualmente é resolvida, a cadeia de promessas muda para o estado resolvido porque você "tratou" o erro e retornou normalmente. Se você lançar ou retornar uma promessa rejeitada no .catch()
manipulador, a promessa retornada permanecerá rejeitada.
No segundo esquema, se a promessa for p
rejeitada, o .catch()
manipulador será chamado. Se você retornar um valor normal ou uma promessa que eventualmente seja resolvida do .catch()
manipulador ("manipulando" assim o erro), a cadeia de promessas muda para o estado resolvido e o .then()
manipulador após o .catch()
será chamado.
Então essa é a diferença # 2. Se o .catch()
manipulador for ANTES, ele pode manipular o erro e permitir que o .then()
manipulador ainda seja chamado.
Quando usar qual:
Use o primeiro esquema se desejar apenas um .catch()
manipulador que possa detectar erros na promessa original p
ou no .then()
manipulador e uma rejeição de p
deve ignorar o .then()
manipulador.
Use o segundo esquema se quiser ser capaz de detectar erros na promessa original p
e talvez (dependendo das condições), permitir que a cadeia de promessa continue como resolvida, executando assim o .then()
manipulador.
A outra opção
Há uma outra opção para usar os dois retornos de chamada que você pode passar para .then()
:
p.then(fn1, fn2)
Isso garante que apenas um de fn1
ou fn2
será chamado. Se p
resolver, então fn1
será chamado. Se p
rejeitar, então fn2
será chamado. Nenhuma mudança de resultado fn1
pode fazer com que fn2
seja chamado ou vice-versa. Portanto, se você deseja ter certeza absoluta de que apenas um de seus dois manipuladores é chamado, independentemente do que acontece nos próprios manipuladores, você pode usar p.then(fn1, fn2)
.