Comment puis-je rejeter une promesse renvoyée par une fonction asynchrone / attendre?
par exemple à l'origine
foo(id: string): Promise<A> {
return new Promise((resolve, reject) => {
someAsyncPromise().then((value)=>resolve(200)).catch((err)=>reject(400))
});
}
Traduire en asynchrone / attendre
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.
});
}
Alors, comment pourrais-je correctement rejeter cette promesse dans ce cas?
Promise
anti-modèle constructeur ! Même le premier extrait aurait dû être écritfoo(id: string): Promise<A> { return someAsyncPromise().then(()=>{ return 200; }, ()=>{ throw 400; }); }
Réponses:
Votre meilleur pari est d'
throw
uneError
enveloppe la valeur, qui se traduit par une promesse rejetée avec uneError
enveloppe la valeur:Vous pouvez également juste
throw
la valeur, mais il n'y a pas d'informations de trace de pile:Alternativement, renvoyez une promesse rejetée avec un
Error
encapsulage de la valeur, mais ce n'est pas idiomatique:(Ou tout simplement
return Promise.reject(400);
, mais encore une fois, il n'y a pas d'informations contextuelles.)(Dans votre cas, comme vous utilisez
TypeScript
et quefoo
la valeur retrn estPromise<A>
, vous utiliseriezreturn Promise.reject<A>(400 /*or error*/);
)Dans une situation
async
/await
, ce dernier est probablement un peu une mauvaise correspondance sémantique, mais cela fonctionne.Si vous lancez un
Error
, cela joue bien avec tout ce qui consomme votrefoo
résultat avec laawait
syntaxe:la source
throw
c'est mieux quePromise.reject()
IMO. Que ce soit ou nonthrow 400
est une question différente. Dans le PO, il rejette 400, et nous pouvons dire qu'il devraitError
plutôt rejeter un .async
fonctions, il n'y a pas de fonctionresolve
oureject
. Il y areturn
etthrow
, qui sont les moyens idiomatiques pour résoudre et rejeter laasync
promesse de la fonction.new
rend cela explicite. Notez également que vous ne pouvez pas le laisser de côté si vous avez uneError
sous-classe (class MyError extends Error
), alors ...Il convient également de mentionner que vous pouvez simplement enchaîner une
catch()
fonction après l'appel de votre opération asynchrone car sous le capot, une promesse est toujours retournée.De cette façon, vous pouvez éviter la
try/catch
syntaxe si vous ne l'aimez pas.la source
async
fonction, je lève une exception, puis je l'attrape bien.catch()
comme si je revenaisPromise.reject
ou appelaisreject
. Je l'aime!await
défaillances possibles en une seule routine. À moins que des cas très spécifiques soient nécessaires pour chacun,await
je ne vois pas pourquoi vous voudriez les attraper comme ça. Juste moi humble avis.await
échec séparément, mais je devais également travailler avec un cadre basé sur des promesses qui rejetait les promesses en cas d'erreur.${host}/user/permissions/repositories_wrong_url/
, accessToken, accessTokenSecret) .catch (err => {logger.error ('Impossible de récupérer les autorisations du référentiel', err); callback (err);})await
mot clé ici.Vous pouvez créer une fonction wrapper qui accepte une promesse et renvoie un tableau avec des données si aucune erreur et l'erreur s'il y a eu une erreur.
Utilisez-le comme ceci dans ES7 et dans une fonction asynchrone :
la source
Une meilleure façon d'écrire la fonction asynchrone serait de renvoyer une promesse en attente depuis le début, puis de traiter les rejets et les résolutions dans le rappel de la promesse, plutôt que de simplement cracher une promesse rejetée en cas d'erreur. Exemple:
Ensuite, vous enchaînez simplement les méthodes sur la promesse retournée:
Source - ce tutoriel:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
la source
J'ai une suggestion pour gérer correctement les rejets dans une nouvelle approche, sans avoir plusieurs blocs try-catch.
D'où la fonction to.ts doit être importée:
Les crédits vont à Dima Grossman dans le lien suivant .
la source
let [err]=
si seulement la vérification des erreurs.Ce n'est pas une réponse à celle de @TJ Crowder. Juste un commentaire répondant au commentaire "Et en fait, si l'exception va être convertie en rejet, je ne sais pas si je suis vraiment gêné s'il s'agit d'une erreur. Mes raisons de ne lancer que l'erreur ne s'appliquent probablement pas. "
si votre code utilise
async
/await
, il est toujours recommandé de rejeter avec unError
au lieu de400
:la source
Je sais que c'est une vieille question, mais je suis juste tombé sur le fil et il semble y avoir une confusion entre les erreurs et le rejet qui va à l'encontre (dans de nombreux cas, au moins) des conseils souvent répétés de ne pas utiliser la gestion des exceptions pour traiter les cas prévus. Pour illustrer: si une méthode asynchrone essaie d'authentifier un utilisateur et que l'authentification échoue, c'est un rejet (l'un des deux cas prévus) et non une erreur (par exemple, si l'API d'authentification n'était pas disponible.)
Pour m'assurer que je ne divisais pas seulement les cheveux, j'ai exécuté un test de performance de trois approches différentes, en utilisant ce code:
Certaines des choses qui s'y trouvent sont incluses en raison de mon incertitude concernant l'interpréteur Javascript (j'aime seulement descendre un trou de lapin à la fois); par exemple, j'ai inclus la
doSomething
fonction et assigné son retour àdummyValue
pour m'assurer que les blocs conditionnels ne seraient pas optimisés.Mes résultats étaient:
Je sais qu'il existe de nombreux cas où cela ne vaut pas la peine de traquer les petites optimisations, mais dans les systèmes à plus grande échelle, ces choses peuvent faire une grande différence cumulative, et c'est une comparaison assez frappante.
SO ... alors que je pense que l'approche de la réponse acceptée est valable dans les cas où vous vous attendez à devoir gérer des erreurs imprévisibles dans une fonction asynchrone, dans les cas où un rejet signifie simplement "vous allez devoir suivre le plan B (ou C ou D…) "Je pense que ma préférence serait de rejeter l'utilisation d'un objet de réponse personnalisé.
la source