Como posso rejeitar uma promessa retornada por uma função assíncrona / aguardada?
por exemplo, originalmente
foo(id: string): Promise<A> {
return new Promise((resolve, reject) => {
someAsyncPromise().then((value)=>resolve(200)).catch((err)=>reject(400))
});
}
Traduzir para assíncrono / aguardar
async foo(id: string): Promise<A> {
try{
await someAsyncPromise();
return 200;
} catch(error) {//here goes if someAsyncPromise() rejected}
return 400; //this will result in a resolved promise.
});
}
Então, como eu poderia rejeitar adequadamente essa promessa neste caso?
Promise
construtor antipadrão ! Mesmo o primeiro trecho deve ter sido escritofoo(id: string): Promise<A> { return someAsyncPromise().then(()=>{ return 200; }, ()=>{ throw 400; }); }
Respostas:
Sua melhor aposta é a de
throw
umaError
embalagem o valor, o que resulta em uma promessa rejeitado com umError
embrulho o valor:Você também pode apenas
throw
o valor, mas não há informações de rastreamento de pilha:Como alternativa, retorne uma promessa rejeitada com um
Error
empacotamento do valor, mas não é idiomático:(Ou apenas
return Promise.reject(400);
, mas novamente, não há informações de contexto.)(No seu caso, como você está usando
TypeScript
efoo
o valor de retrnPromise<A>
, você usariareturn Promise.reject<A>(400 /*or error*/);
)Em uma situação
async
/await
, esse último provavelmente é um erro de correspondência semântica, mas funciona.Se você joga um
Error
, isso funciona bem com qualquer coisa que consome ofoo
resultado da sua comawait
sintaxe:fonte
throw
é melhor que oPromise.reject()
IMO. Sethrow 400
é uma pergunta diferente. No OP, ele está rejeitando 400, e podemos argumentar que ele deveria rejeitar umError
.async
funções, não existeresolve
oureject
funciona. Existemreturn
ethrow
, quais são as formas idiomáticas de resolver e rejeitar aasync
promessa da função.new
torna isso explícito. Além disso, note que você não pode deixá-lo fora se você tem umaError
subclasse (class MyError extends Error
), então ...Provavelmente, também deve ser mencionado que você pode simplesmente encadear uma
catch()
função após a chamada de sua operação assíncrona, porque, sob o capô, uma promessa ainda é retornada.Dessa forma, você pode evitar a
try/catch
sintaxe se não gostar.fonte
async
função, ligo a exceção e a pego bem.catch()
como se retornassePromise.reject
ou chamassereject
. Eu gosto disso!await
falhas possíveis em uma rotina. A menos que casos muito específicos sejam necessários para cada umawait
, não vejo por que você gostaria de capturá-los assim. Apenas eu humilde opinião.await
falha separadamente, também precisava trabalhar com uma estrutura baseada em Promessa que rejeitasse as promessas por erro.${host}/user/permissions/repositories_wrong_url/
, accessToken, accessTokenSecret) .catch (err => {logger.error ('Não foi possível obter permissões do repositório', err); callback (err);})await
palavra-chave aqui.Você pode criar uma função de wrapper que aceite uma promessa e retorne uma matriz com dados se não houver erro e o erro se houver um erro.
Use-o assim no ES7 e em uma função assíncrona :
fonte
Uma maneira melhor de escrever a função assíncrona seria retornando uma promessa pendente desde o início e, em seguida, processando rejeições e resoluções no retorno de chamada da promessa, em vez de apenas citar uma promessa rejeitada por erro. Exemplo:
Então você apenas encadeia métodos na promessa retornada:
Fonte - este tutorial:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
fonte
Tenho uma sugestão para lidar adequadamente com rejeições em uma nova abordagem, sem ter vários blocos try-catch.
Para onde a função to.ts deve ser importada de:
Os créditos vão para Dima Grossman no link a seguir .
fonte
let [err]=
se apenas verificar erros.Esta não é uma resposta à pergunta de @TJ Crowder. Apenas um comentário respondendo ao comentário "E, na verdade, se a exceção for convertida em uma rejeição, não tenho certeza se estou realmente incomodado se for um Erro. Minhas razões para lançar apenas o Erro provavelmente não se aplicam. "
se o seu código estiver usando
async
/await
, ainda é uma boa prática rejeitar com um emError
vez de400
:fonte
Sei que essa é uma pergunta antiga, mas acabei de me deparar com o tópico e parece haver aqui uma confusão entre erros e rejeição que ocorre (em muitos casos, pelo menos) nos conselhos frequentemente repetidos de não usar o tratamento de exceções para lidar com casos previstos. Para ilustrar: se um método assíncrono está tentando autenticar um usuário e a autenticação falha, isso é uma rejeição (um dos dois casos previstos) e não um erro (por exemplo, se a API de autenticação não estiver disponível).
Para ter certeza de que não estava apenas dividindo os cabelos, executei um teste de desempenho com três abordagens diferentes, usando este código:
Algumas das coisas que estão lá dentro estão incluídas por causa da minha incerteza em relação ao interpretador Javascript (eu só gosto de descer uma toca de coelho por vez); por exemplo, incluí a
doSomething
função e designei seu retornodummyValue
para garantir que os blocos condicionais não fossem otimizados.Meus resultados foram:
Sei que existem muitos casos em que não vale a pena procurar pequenas otimizações, mas em sistemas de larga escala essas coisas podem fazer uma grande diferença cumulativa, e essa é uma comparação bastante clara.
ASSIM ... enquanto eu acho que a abordagem da resposta aceita é sólida nos casos em que você espera lidar com erros imprevisíveis em uma função assíncrona, nos casos em que uma rejeição significa simplesmente "você terá que seguir o plano B (ou C, ou D ...) "Acho que minha preferência seria rejeitar o uso de um objeto de resposta personalizado.
fonte