2017-03-20 5 views
0

verwenden möchte ich example dies anzupassen:Scala Zukunft nicht richtig aufgerufen wird, wenn implizite Klasse

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) } 
} 

Zur Unterstützung Anrufe wie: myFuture.retry(Seq(1.seconds, 5.seconds, 10.seconds)).map {data => process(data)}.

Hier ist, wie ich es umgesetzt:

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)) } 
    } 

    } 

} 

Ich bemerkte, dass die retry Methode richtig genannt wird, aber es ist nicht die ursprüngliche Zukunft zu bewerten. Beim Debugging habe ich gemerkt, dass der Wert der Zukunft Failure ist und ich denke, das ist ein Hinweis darauf, dass ich mich nie richtig erholen werde, was bedeutet, dass ich niemals die ursprüngliche Zukunft nennen werde.

Wie kann ich das beheben?

Antwort

3

Der entscheidende Punkt ist hier die Tatsache, dass Ihre Future by-Wert anruf ist, während das Beispiel des Future Call-by-Name ist, wie sie in den => vor seiner Art angegeben.

Ein call-by-value-Argument (scala default) wird einmal vor dem Aufruf der Funktion ausgewertet und dann als val behandelt.

Ein Call-by-Name-Argument (definiert mit => T Typ) wird nicht vor Funktionsaufruf ausgewertet, sondern wird als "Thunk" angegeben, das jedes Mal ausgeführt wird, wenn es innerhalb der Funktion aufgerufen wird. Dies ist das gleiche wie mit einem def.

Wie sich herausstellt, können Sie eine implizite Klasse mit einem Call-by-Name-Argument erstellen. Sie müssen also einfach den Doppelpfeil f: => Future[T] in Ihr Klassenargument einfügen, um das gewünschte Ergebnis zu erhalten.

Verwandte Themen