2017-03-20 2 views
0

Je veux adapter ce example:Scala avenir n'est pas correctement appelé lors de l'utilisation de classe implicite

def retry[T](f: => Future[T], delays: Seq[FiniteDuration])(implicit ec: ExecutionContext, s: Scheduler): Future[T] = { 
    f recoverWith { case _ if delays.nonEmpty => after(delays.head, s)(retry(f, delays.tail) } 
} 

Pour soutenir les appels comme: myFuture.retry(Seq(1.seconds, 5.seconds, 10.seconds)).map {data => process(data)}.

Voilà comment j'implémenté:

import akka.pattern.after 
import akka.actor.Scheduler 
import scala.concurrent.{ExecutionContext, Future} 
import scala.concurrent.duration.FiniteDuration 

object FutureExtension { 

    implicit class FutureExtension[T](f: Future[T]) { 

    def retry(delays: Seq[FiniteDuration])(implicit ec: ExecutionContext, s: Scheduler): Future[T] = { 
     f recoverWith { case _ if delays.nonEmpty => after(delays.head, s)(f.retry(delays.tail)) } 
    } 

    } 

} 

je remarquai que la méthode est appelée retry correctement, mais pas l'évaluation de l'avenir d'origine. Lors du débogage, j'ai remarqué que la valeur du futur est Failure et je suppose que c'est une indication que je ne récupérerai jamais correctement, ce qui signifie que je n'appellerai jamais le futur original.

Comment puis-je résoudre ce problème?

Répondre

3

Le point clé ici est le fait que votre Future est l'appel par valeur tandis que l'exemple Future est appelé par son nom, comme indiqué par le => avant son type.

Un argument d'appel par valeur (valeur par défaut scala) est évalué une fois avant l'appel de la fonction, puis traité comme val.

Un argument d'appel par le nom (défini avec le type => T) n'est pas évalué avant l'appel de la fonction, mais est donné comme un "thunk" qui sera exécuté chaque fois qu'il est appelé dans la fonction. C'est la même chose que d'avoir un def. Comme il s'avère, vous pouvez créer une classe implicite avec un argument call-by-name, donc vous avez juste besoin d'ajouter la double flèche f: => Future[T] dans votre argument de classe pour obtenir ce que vous désirez.