Comment puis-je obtenir les exceptions levées dans un Scala Avenir?
J'ai travaillé ma réponse à Est-il un standard de Scala fonction pour l'exécution d'un bloc avec un délai d'attente?, et l'ont exécuté un problème si une exception est levée dans un Avenir.
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
awaitAll(timeoutMs, future(f)).head.asInstanceOf[Option[T]]
}
De sorte que
runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)
Mais si je jette une exception dans mon quartier, il n'y a pas de fuite, mais il est avalé, de sorte que le suivant échoue avec "..pas une exception a été levée"
intercept[Exception] {
runWithTimeout(50) { throw new Exception("deliberate") }
}.getMessage should equal("deliberate")
Syserr a une trace de la pile avec le message
<function0>: caught java.lang.Exception: deliberate
mais je ne trouve pas où dans le Scala runtime qui est imprimé.
En dehors de habillage de f dans un autre bloc, qui attrape les exceptions et les propage si jetés, est-il possible de convaincre awaitAll et/ou à venir jeter?
Il est imprimé vraisemblablement parce qu'il s'est passé au fil du UncaughtExceptionHandler. Vous pouvez définir votre propre gestionnaire, mais ce ne serait pas vous permettre de lancer l'exception dans un thread différent.
Jetez un oeil à Fingales terme (github.com/twitter/finagle), recherche pour "Timeout" et Akka akka.io/docs/akka/1.1.2/scala/futures.html
Jetez un oeil à Fingales terme (github.com/twitter/finagle), recherche pour "Timeout" et Akka akka.io/docs/akka/1.1.2/scala/futures.html
OriginalL'auteur Duncan McGregor | 2011-06-03
Vous devez vous connecter pour publier un commentaire.
Réponse courte: non.
Exceptions ne font pas ce que vous voulez, quand vous travaillez dans une tige de contexte, parce que vous voulez savoir à propos de l'exception de l'appelant, et l'exception qui se passe dans le futur d'ariane.
Au lieu de cela, si vous voulez savoir ce que l'exception est le cas, vous devez retourner un
Either[Exception,WhatYouWant]
--bien sûr, vous avez à les attraper que l'exception prévue dans l'avenir et de les emballer.Future.get()
jetteExecutionException
, dans lequel il s'enroule toute Exception à l'exécution du code. C'était mon modèle ici.McGregor - je ne sais pas comment Java accomplit, mais si c'est fait comme une bibliothèque, il n'y a pas beaucoup de choix mais pour avoir la discussion prendre de l'exception, de l'emballage, et de traiter avec elle sur l'autre extrémité. Ma conjecture est que Java fait pour vous car il ne dispose pas d'un mécanisme général pour le permettre; Scala a vous faire vous-même (en utilisant le mécanisme général fourni pour de telles choses).
Merci - Soit, ressemble à un autre idiome que je vais l'apprendre!
J'ai accepté cette réponse est la plus utile et la condition d'une mise en œuvre en tant que mon propre réponse. Notez que @Vikto Klang donne la solution la plus simple, mais pas pour le standard de Scala Avenir.
Vous pouvez l'utiliser au lieu d'Essayer de
OriginalL'auteur Rex Kerr
Disclaimer: je travaille pour Typesafe
Ou...... vous pouvez utiliser Akka et il vous donnera ce que vous voulez sans vous avoir à passer à travers des cerceaux pour elle.
Puis
Lève l'exception qui s'est passé dans l'acteur
vous donnera une Option[Lancer]
OriginalL'auteur Viktor Klang
Mon travail dans @Rex Kerr suggestion, j'ai créé
de sorte que
Encore une fois, je suis un peu à la Scala de novice, donc serait la bienvenue de la rétroaction.
OriginalL'auteur Duncan McGregor
scala.concurrent.ops.future
comprend la gestion des exceptions.Ainsi, au lieu de l'importation de
scala.actors.Futures.future
, l'importationscala.concurrent.ops.future instead
.Que le simple changement dans l'importation est il sera la cause de l'appelant à l'appel .obtenir à relever de l'exception. Il fonctionne très bien!
scala.concurrent.ops.future
a été supprimé en Scala 2.11 et, par conséquent, cette réponse ne s'applique plus: github.com/scala/scala/commit/...OriginalL'auteur Eric Pabst
Ou de l'utilisation
Future.liftTryTry
, il tourne à partir deFuture[Object]
àFuture[Try[Object]]
, et vous pouvez le match sur leTry[Object]
et vérifier une exceptioncase Throw(e)
et log /sortie gracieusementOriginalL'auteur zainahamid
Vous avez besoin pour remplacer la méthode
exceptionHandler
afin d'intercepter des exceptions. Si votre option est de définir votre proprefuture
méthode de sorte qu'il crée une MyFutureActor avec exceptionHandler.EDIT: FutureActor est privé, afin de sous-classement, il n'est pas possible.
Une autre option est d'utiliser des liens pour savoir quand les exceptions qui s'est passé.
Cependant, je pense que Rex Kerr approche est de mieux - juste envelopper la fonction dans quelque chose qui va attraper l'Exception. Trop mauvais
future
n'est pas déjà le faire.OriginalL'auteur IttayD