57 votes

Scala récupérer ou récupérerAvec

Nous développons des systèmes dans notre entreprise à Scala et nous avons des doutes. Nous discutions de la façon de mapper les futures exceptions et nous ne savons pas quand nous devrions utiliser l'option 1 ou l'option 2.

 val created: Future[...] = ???
 

Option 1:

 val a = created recover {   
  case e: database.ADBException =>
    logger.error("Failed ...", e)
    throw new business.ABusinessException("Failed ...", e) 
}
 

Option 2:

 val a = created recoverWith {   
  case e: database.ADBException =>
    logger.error("Failed ...", e)
    Future.failed(new business.ABusinessException("Failed ...", e))
}
 

Quelqu'un pourrait-il expliquer quand dois-je choisir l'option 1 ou l'option 2? Quel est le diff?

84voto

Aivean Points 2564

Eh bien, la réponse est clairement décrite dans scaladocs:

  /** Creates a new future that will handle any matching throwable that this
   *  future might contain. If there is no match, or if this future contains
   *  a valid result then the new future will contain the same.
   *
   *  Example:
   *
   *  {{{
   *  Future (6 / 0) recover { case e: ArithmeticException => 0 } // result: 0
   *  Future (6 / 0) recover { case e: NotFoundException   => 0 } // result: exception
   *  Future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3
   *  }}}
   */
  def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = {

  /** Creates a new future that will handle any matching throwable that this
   *  future might contain by assigning it a value of another future.
   *
   *  If there is no match, or if this future contains
   *  a valid result then the new future will contain the same result.
   *
   *  Example:
   *
   *  {{{
   *  val f = Future { Int.MaxValue }
   *  Future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue
   *  }}}
   */
  def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U] = {

recover enveloppements plaine résultat en Future pour vous (analogue de l' map), tandis que l' recoverWith prévoit Future que le résultat (analogue de l' flatMap).

Donc, ici, c'est la règle de base:

Si vous retrouvez avec quelque chose qui renvoie déjà Future, utilisez recoverWith, sinon utilisez recover.

upd Dans votre cas, à l'aide de recover est préféré, comme recover va envelopper votre exception en Future pour vous. Sinon il n'y a pas de gain de performance ou de n'importe quoi, donc il vous suffit d'éviter réutilisable.

20voto

Tomer Ben David Points 36

À l'aide de recoverWith il vous est demandé de retourner un enveloppé à l'avenir, à l'aide de recover il vous est demandé de lever une exception.

.recoverWith # => Future.failed(t)
.recover # => throw t

Je préfère utiliser l' recoverWith parce que je pense que la programmation fonctionnelle préfère le retour des objets que de lancer des exceptions, qui est de moins de un style fonctionnel, même si c'est interne bloc de code, je pense qu'il tient toujours..

Cependant si j'ai déjà un morceau de code dans le bloc de récupération qui peut lever une exception alors, dans ce cas, plutôt que de l'attraper et l'enveloppant avec Future, ou de l'Essayer, je pourrais tout aussi bien exécuter ce morceau de code en combinaison avec d' recover et il serait en mesure de gérer l'exception d'emballage pour vous, ce qui permettrait de rendre le code plus lisible et plus compact.

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