Comment puis-je saisir une erreur asynchrone en utilisant les promesses de JS?

Est-il possible d'attraper des erreurs asynchrones en utilisant la syntaxe ES6 .catch des promesses? Par exemple, les éléments suivants ne fonctionnent pas (la capture ne capture pas l'erreur):

 new Promise((resolve, reject)=>{ setTimeout(()=>{throw new Error("uh oh")}, 1); }).then(number=>{ console.log("Number: " + number); }).catch(e=>{ console.log("Error: " + e); }); 

Mais cette version synchrone:

 new Promise((resolve, reject)=>{ throw new Error("uh oh"); }).then(number=>{ console.log("Number: " + number); }).catch(e=>{ console.log("Error: " + e); }); 

Est-ce que la seule solution est de faire quelque chose comme le suivant, en utilisant un bloc try / catch et de reject l'erreur dans la capture?

 new Promise((resolve, reject)=>{ try { setTimeout(()=>{throw new Error("uh oh")}, 1); } catch(e) { reject(e); } }).then(number=>{ console.log("Number: " + number); }).catch(e=>{ console.log("Error: " + e); }); 

Pour l'objet de cette question, supposons que la partie du code qui lance l'erreur se trouve dans une autre fonction nommée, donc elle n'a pas accès à la fonction de reject .

Merci!!

Edit: Voici un exemple plus complet de ce que j'aimerais faire dans JSFiddle.

Utilisez resolve() , reject() dans Promise constructor. Manipulez l'erreur soit sur onRejected ou .catch() .

Remarque: une fois que l'erreur est traitée, onFulfilled en chaîne .then() , le cas échéant, devrait être atteinte, à moins que le throw soit utilisé à l'intérieur de onRejected ou .catch() , pour passer explicitement l'erreur en chaîne .then(_, onRejected) ou .catch()

 function fn() { throw new Error("uh oh") } new Promise((resolve, reject) => { setTimeout(() => { try { resolve(fn()) } catch (e) { reject(e) } }, 1); }).then(number => { console.log("Number: " + number); }, e => { console.log("Error: " + e); }); 

Il n'y a aucun moyen d'attraper une erreur lancée comme votre premier exemple. Le problème ici est que vous utilisez l'Antipattern Explicit Promise Construction. Vous essayez de faire en sorte que le constructeur Promise fasse plus que ce qu'il doit faire.

Au lieu de cela, vous devriez promener la plus petite quantité de fonctionnalités asynchrones et construire en plus de cela. Dans ce cas, cela impliquerait de produire une promesse qui attend un certain temps avant de résoudre. La plupart des bibliothèques de promesses tierces ont déjà une méthode .delay() , mais il est très facile de créer la vôtre:

 let delay = duration => new Promise(resolve => setTimeout(resolve, duration)); 

Ensuite, vous pouvez construire en plus de cela et attraper l'erreur facilement:

 let delay = duration => new Promise(resolve => setTimeout(resolve, duration)); delay(1) .then(() => { throw new Error("uh oh"); }) .then(number => { console.log("Number: " + number); }).catch(e => { console.log("Error: " + e); }); 

"Pour l'objet de cette question, supposons que la partie du code qui lance l'erreur se trouve dans une autre fonction nommée, de sorte qu'elle n'a pas accès à la fonction de rejet." – Christopher Shroba

"Cette fonction (non existante dans votre code) renvoie-t-elle une promesse?" – Jaromanda X

"Oui, l'autre fonction renvoie une promesse normalement, mais parce qu'une fonction asynchrone à l'intérieur de cette fonction lance une erreur , toute la fonction lance une erreur". – Christopher Shroba

Bien après, affichez votre code, car votre capacité à décrire le problème avec l'anglais ne sera jamais aussi bonne que le code actuel. Par "fonction asynchrone", voulez-vous dire une fonction qui renvoie une promesse? Si c'est le cas …


Peu importe la profondeur des erreurs dans vos promesses. Voici un exemple de fonction three qui appelle une fonction two qui appelle une fonction qui a le potentiel de lancer une erreur dans le cas où le JSON est mal formé. Chaque étape apporte une contribution précieuse au calcul final, mais dans le cas où l' one émettrait une erreur, elle passera à travers toute la chaîne de promesses.

 const one = (json) => new Promise((resolve, reject) => { resolve(JSON.parse(json)) }) const two = (json) => one(json).then(data => data.hello) const three = (json) => two(json).then(hello => hello.toUpperCase()) three('{"hello":"world"}').then(console.log, console.error) // "WORLD" three('bad json').then(console.log, console.error) // Error: unexpected token b in JSON at position 0