143 votes

Comment puis-je relancer une exception en Javascript, tout en préservant la pile ?

En Javascript, supposons que je veuille effectuer un nettoyage lorsqu'une exception se produit, mais que je laisse l'exception continuer à se propager sur la pile, par exemple :

try {
  enterAwesomeMode();
  doRiskyStuff(); // might throw an exception
} catch (e) {
  leaveAwesomeMode();
  throw e;
}
doMoreStuff();
leaveAwesomeMode();

Le problème avec ce code est que le fait d'attraper et de relancer l'exception entraîne la perte des informations de la trace de pile jusqu'à ce point, de sorte que si l'exception est ensuite attrapée à nouveau, plus haut sur la pile, la trace de pile ne va que jusqu'au nouveau lancement. Cela craint car cela signifie qu'elle ne contient pas la fonction qui a réellement lancé l'exception.

Il s'avère que try..finally a le même comportement, au moins dans Chrome (c'est-à-dire que ce n'est pas le re-throw qui pose problème, mais la présence d'un bloc de gestion des exceptions).

Quelqu'un connaît-il un moyen de relancer une exception en Javascript tout en conservant la trace de la pile associée à cette exception ? A défaut, pourquoi ne pas suggérer d'autres moyens d'ajouter des gestionnaires de nettoyage à l'abri des exceptions, tout en capturant des traces de pile complètes lorsqu'une exception se produit ?

Merci de vos conseils :)

75voto

Glenn Maynard Points 24451

Il s'agit d'un bogue dans Chrome. Le fait de relancer une exception devrait permettre de conserver la trace de l'appel.

http://code.google.com/p/chromium/issues/detail?id=60240

Je ne connais pas de solution de contournement.

Je ne vois pas où est le problème. Je vois des exceptions qui n'apparaissent pas silencieusement dans la console d'erreur dans certains cas après un finally, mais cela semble être corrigé dans les versions de développement.

22voto

Mike Stay Points 398

La propriété de pile d'un objet Error est créée en même temps que l'objet Error lui-même, et non au moment où il est lancé. Ils sont souvent identiques en raison de l'idiome

   throw new Error("message");

et si vous utilisez le code tel que vous l'avez écrit, la propriété de la pile sera no est modifié lorsque vous relancez l'erreur.

1voto

Ofer Segev Points 131

Comme indiqué, la pile est un instantané créé lors de l'exécution du programme new Error(...) et on ne peut donc pas vraiment lancer l'erreur avec la même pile.

Une solution de contournement que j'ai utilisée consiste à console.error la pile avant de la lancer :

  console.error(err.stack);
  throw err;

Ce n'est pas parfait, mais cela permet d'obtenir suffisamment d'informations pouvant être déboguées, ainsi que la pile de l'erreur initiale.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X