web-dev-qa-db-fra.com

Puis-je détecter une erreur asynchrone sans utiliser l'attente?

Les erreurs d'un appel asynchrone non attendu peuvent-elles être interceptées, envoyées à un essai/capture d'encapsulation d'origine ou déclencher une exception non interceptée?

Voici un exemple de ce que je veux dire:

async function fn1() {
    console.log('executing fn1');
}

async function fn2() {
    console.log('executing fn2');
    throw new Error('from fn2');
}

async function test() {
    try {
        await fn1();
        fn2();
    }
    catch(e) {
        console.log('caught error inside test:', e);
    }
}

test();

Dans ce scénario, l'erreur renvoyée par fn2 sera avalé en silence et ne sera certainement pas pris par l'original try/catch. Je pense que c'est un comportement attendu, car fn2 est très probablement poussé vers la boucle d'événements pour se terminer à un moment donné dans le futur, et test ne se soucie pas quand il se termine (ce qui est intentionnel).

Existe-t-il un moyen de s'assurer que les erreurs ne sont pas accidentellement avalées par une structure comme celle-ci, à moins de mettre un try/catch interne à fn2 et faire quelque chose comme émettre une erreur? Je me contenterais même d'une erreur non capturée sans savoir comment l'attraper, je pense - je ne m'attends pas à ce que les erreurs lancées soient un flux de programme typique avec ce que j'écris, mais avaler des erreurs rend le débogage relativement ennuyeux.

Remarque: j'utilise Babel pour transpiler le code à l'aide de la transformation babel-runtime et je l'exécute avec le nœud.

28
dvlsg

Le traitement des promesses natives rejetées non gérées (et async/attente utilise des promesses natives) est une fonctionnalité prise en charge maintenant dans V8. Il est utilisé dans la dernière Chrome pour afficher les informations de débogage lorsqu'une promesse rejetée n'est pas gérée; essayez ce qui suit sur Babel REPL :

async function executor() {
  console.log("execute");
}

async function doStuff() {
  console.log("do stuff");
  throw new Error("omg");
}

function handleException() {
  console.error("Exception handled");
}

(async function() {
  try {
      await executor();
      doStuff();
  } catch(e) {
      handleException();
  }
})()

Vous voyez que, même si l'exception de doStuff() est perdue (car nous n'utilisons pas await lorsque nous l'appelons), Chrome enregistre qu'un la promesse rejetée n'a pas été gérée par la console:

Screenshot

Ceci est également disponible dans Node.js 4.0+, bien qu'il nécessite d'écouter n événement spécial unhandledRejection :

process.on('unhandledRejection', function(reason, p) {
    console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);
    // application specific logging, throwing an error, or other logic here
});
27
Michelle Tilley