Eu li vários artigos sobre esse assunto, mas ainda não está claro para mim se há uma diferença entre Promise.reject
vs. lançar um erro. Por exemplo,
Usando Promise.reject
return asyncIsPermitted()
.then(function(result) {
if (result === true) {
return true;
}
else {
return Promise.reject(new PermissionDenied());
}
});
Usando throw
return asyncIsPermitted()
.then(function(result) {
if (result === true) {
return true;
}
else {
throw new PermissionDenied();
}
});
Minha preferência é usar throw
simplesmente porque é mais curto, mas queria saber se existe alguma vantagem de uma sobre a outra.
javascript
promise
Naresh
fonte
fonte
.then()
manipulador captura a exceção lançada e a transforma em uma promessa rejeitada automaticamente. Como li que as exceções lançadas não são particularmente rápidas de executar, acho que devolver a promessa rejeitada pode ser um pouco mais rápida de executar, mas você teria que criar um teste em vários navegadores modernos, se isso fosse importante. Eu pessoalmente usothrow
porque gosto da legibilidade.throw
é que isso não resultaria em uma promessa rejeitada se fosse lançada de dentro de um retorno de chamada assíncrono, como um setTimeout. jsfiddle.net/m07van33 @Blondie, sua resposta estava correta.reject
lo da minha lista de parâmetros.Respostas:
Não há vantagem em usar um vs o outro, mas há um caso específico em
throw
que não funciona. No entanto, esses casos podem ser corrigidos.Sempre que você estiver dentro de um retorno de chamada promissor, poderá usá-lo
throw
. No entanto, se você estiver em outro retorno de chamada assíncrono, deverá usarreject
.Por exemplo, isso não acionará a captura:
Em vez disso, você fica com uma promessa não resolvida e uma exceção não capturada. Esse é um caso em que você deseja usar
reject
. No entanto, você pode corrigir isso de duas maneiras.fonte
throw error
, também não podem usarreturn Promise.reject(err)
qual é o que o OP estava nos pedindo para comparar. É basicamente por isso que você não deve colocar retornos de chamada assíncronos dentro das promessas. Promise tudo que é assíncrono e você não tem essas restrições.Array#forEach
) e com aqueles, jogando dentro deles funcionaria.throw
que não funcionarão ePromise.reject
é uma escolha melhor. No entanto, os trechos não são afetados por nenhuma dessas duas opções e fornecem o mesmo resultado, independentemente do que você escolher. Estou esquecendo de algo?reject
que foi passado para onew Promise(fn)
retorno de chamada.return Promise.reject()
ethrow
. Ele não menciona oreject
retorno de chamada fornecido nanew Promise(function(resolve, reject))
construção. Portanto, enquanto seus dois trechos demonstram corretamente quando você deve usar o retorno de chamada de resolução, a pergunta do OP não era essa.Outro fato importante é que
reject()
NÃO encerra o fluxo de controle como umareturn
instrução. Em contrastethrow
, termina o fluxo de controle.Exemplo:
vs
fonte
return reject()
, para que a próxima linha não seja executada.return reject()
é simplesmente um atalho para, por exemplo, oreject(); return
que você deseja é encerrar o fluxo. O valor de retorno do executor (a função passada paranew Promise
) não é usado, portanto isso é seguro.Sim, a maior diferença é que rejeitar é uma função de retorno de chamada que é executada após a promessa ser rejeitada, enquanto que o throw não pode ser usado de forma assíncrona. Se você optar por usar rejeitar, seu código continuará sendo executado normalmente de maneira assíncrona, enquanto o throw priorizará a conclusão da função de resolução (essa função será executada imediatamente).
Um exemplo que vi que ajudou a esclarecer o problema para mim foi que você pode definir uma função Timeout com rejeitar, por exemplo:
Não foi possível escrever acima com throw.
No seu pequeno exemplo, a diferença é indistinguível, mas ao lidar com um conceito assíncrono mais complicado, a diferença entre os dois pode ser drástica.
fonte
TLDR: uma função é difícil de usar quando, às vezes, retorna uma promessa e às vezes gera uma exceção. Ao escrever uma função assíncrona, prefira sinalizar falha retornando uma promessa rejeitada
Seu exemplo em particular ofusca algumas distinções importantes entre eles:
Como você está manipulando erros dentro de uma cadeia de promessas, as exceções lançadas são convertidas automaticamente em promessas rejeitadas. Isso pode explicar por que eles parecem ser intercambiáveis - eles não são.
Considere a situação abaixo:
Isso seria um antipadrão, pois você precisaria oferecer suporte a casos de erro assíncrono e sincronizado. Pode parecer algo como:
Não é bom e é exatamente aqui que
Promise.reject
(disponível no escopo global) vem o resgate e se diferencia efetivamentethrow
. O refator passa a ser:Agora, você pode usar apenas um
catch()
para falhas de rede e a verificação de erro síncrono por falta de tokens:fonte
Promise.reject
outhrow
quando deseja retornar uma promessa rejeitada (uma promessa que passará para a próxima.catch()
).checkCredentials(x).then(onFulfilled).catch(e) {}
ecatch
lidar com o caso de rejeição e o caso de erro lançado?Um exemplo para experimentar. Apenas mude isVersionThrow para false para usar rejeitar em vez de lançar.
fonte