2017-03-10 6 views
0

Ich versuche, den Wert aus einem Codeschnipsel zu ziehen, der zu einem Future führt, aber wenn ich den Code durchführe, stellt es sich heraus, dass es nie die onComplete Funktion eingibt. Gibt es irgendetwas, was ich falsch mache?Scala Future tritt nicht onComplete() ein

Ich habe versucht, auch eine Karte verwenden, da es in anderen Beiträgen vorgeschlagen wurde, haben aber keinen Erfolg hatte

override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer] = { 

     //query for customer in db 
     val avroCustomer: Future[AvroCustomer] = customerByPhone(phoneNumber) 

     avroCustomer.onComplete({ 
     case Success(null) => { 
      createUserAndEvent(phoneNumber, creationReason, 1.0) 
     } 

     case Success(customer) => { 
      Future.successful(customer) 
     } 

     case Failure(exception) => { 

     } 
}) 
+0

Warten Sie auf die 'Future' zu fertig mit dem Code, der das aufruft? Erhalten Sie vielleicht ein "Scheitern" und ignorieren es? – jkinkead

+1

Vielleicht ist Ihre Zukunft tatsächlich nicht für eine sehr lange Zeit abgeschlossen. Möglicherweise möchten Sie 'Await.result' zum Debuggen versuchen. – francoisr

+1

Futures sind _eventuell_ da -> Sie müssen irgendwann auf sie warten, wie @jkinkead es ausdrückte. Wenn Sie am Ende des Programms eine "Zukunft" ausführen und nicht darauf warten, werden Sie nie Ergebnisse sehen. – sebszyller

Antwort

2

Antwort auf den Kommentar zu erweitern. Dieses Dummy-Programm wird nichts drucken.

import scala.concurrent.Future 
import scala.util.{Failure, Success} 
import scala.concurrent.ExecutionContext.Implicits.global 

object Quickie { 
    def main(args: Array[String]): Unit = { 
    val addOneInFuture: Future[Int] = Future(addOne(3)) 

    addOneInFuture.onComplete { 
     case Success(s) => println(s) 
     case Failure(ex) => println(ex.toString) 
     case _ => println("what the hell happened") 
    } 

    } 

    def addOne(x: Int): Int = x + 1 
} 

ich einen neuen Thread feuern, aber da der Wert nie benötigt wird, werde ich nicht das 4. Allerdings gedruckt sehen, fügen Sie ein einfaches Await, Threed.sleep(_eternity_), Teufel noch eine andere println und Sie werden sehen, das Ergebnis. Eine Sache zu verstehen über Futures in Scala ist, dass Sie sie als Sammlungen zu behandeln und zu behandeln (daher gibt es for-comprehensions für sie) und Sie wollen selten etwas tun und drucken. Wenn Sie eine db oder Ruhe IO machen, werden Sie die Daten trotzdem weiter verarbeiten.

Es gibt eine alte, aber goldene Blogserie von Daniel Westheide, die Sie lesen können. http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html

1

Imo, anstatt eine OnComplete zu verwenden, die es wird bestätigt, was Sie wollen (OnComplete ist ein Verfahren vom Typ Unit), zuerst, können Sie die Ausnahme auf der DB-Seite versuchen zu kontrollieren, entweder mit einem Try-Typ oder eine Wiederherstellung, dann lassen Sie Ihre Methode eine Option[AvroCustomer] zurückgeben.

Dies ist ein perfekter Anwendungsfall für scala Optionale Wrapper-Typen (die Scala-tastic Arbeitsweise mit Null-Typen). Wenn customerByPhone aus irgendeinem Grund null zurückgibt, können Sie es auf der Seite der DB-Funktion abfangen und in einen optionalen Typ umwandeln.

dh sehr schnell, wenn es sich um ein Nullable Type ist:

def customerByPhone(s: String) = { 
    ... //Some code 
    db.run(query).map(Option(_)) 
} 

Dies erzeugt nun eine Option[avroCustomer], die Sie auf diese Weise dann ist die Kette kann:

override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer] = { 

     //query for customer in db 
     customerByPhone(phoneNumber).flatMap { 
     case Some(customer) => Future.successful(customer) 

     case None => createUserAndEvent(phoneNumber, creationReason, 1.0) //I'm assuming this returns a futures. 
     } 
}  
Verwandte Themen