2016-08-22 5 views
4

In meiner Methode1 muss ich eine andere Methode2 asynchron aufrufen, die Option (Ergebnis1) zurückgibt. Dann, wenn result1 leer ist, muss ich eine andere Methode3 asynchron aufrufen, aber wenn result1 NICHT leer ist, muss ich sie einfach zurückgeben. HierScala Future - zum Verständnis, Mix Sync und Async

ist die Methode:

def signIn(username: String): Future[User] = { 
    for { 
     foundUser <- userService.findByUsername(username) // this method returns Future[Option[User]], 
     // foundUser is Option[User] 
     user <- if (foundUser.isEmpty) { 
     val newUser = User(username = "User123") 
     userService.create(newUser).map(Some(_)) // this method returns Future[Option[User]] 
     } 
     else 
     // Here I want to return just foundUser, of course, it is not possible. 
     // IS THIS APPROACH CORRECT?? DOES THIS LINE CREATE ASYNCHRONOUS CALL?   
     Future.successful(foundUser) 
    } yield user 
    } 

Frage ist:

Future.successful(foundUser) - ist dieser Ansatz richtig in dem obigen Code? Erstellt diese Zeile einen asynchronen Aufruf? Wenn ja, wie vermeide ich das? Ich habe bereits foundUser asynchron abgerufen, und ich möchte nicht zusätzliche Async-Aufruf nur um bereits abgerufenen Wert zurückgeben.

Antwort

4

Future.successful stellt keine zusätzliche Funktion auf dem bereitgestellten ExecutionContext. Es nutzt einfach eine Promise[T] zu einem Future[T] abgeschlossen zu erstellen:

/** Creates an already completed Future with the specified result. 
    * 
    * @tparam T  the type of the value in the future 
    * @param result the given successful value 
    * @return   the newly created `Future` instance 
    */ 
    def successful[T](result: T): Future[T] = Promise.successful(result).future 

Als Randbemerkung, können Sie die Menge von vorformulierten reduzieren Option.fold mit:

def signIn(username: String): Future[User] = 
    userService 
    .findByUsername(username) 
    .flatMap(_.fold(userService.create(User(username = "User123")))(Future.successful(_)) 
+0

danke @Yuval Itzchakov – Teimuraz

+0

durch die Art und Weise, wenn ich schreibe Zukunft {foundUser} statt Future.successful (foundUser), es asynchron ausgeführt wird, nicht wahr? – Teimuraz

+0

@ moreo Ja, es wird das Einreihen der Funktion in den 'ExecutionContext' verursachen. –

1

@Yuval Itzchakov Ihre Frage beantwortet, sondern als Randnotiz, können Sie flatMap mit Mustervergleich direkt in Ihrem Fall verwenden. Ich persönlich finde es besser lesbar:

def signIn(username: String): Future[User] = 
    userService.findByUsername(username) 
    .flatMap { 
     case Some(user) => Future.successful(user) 
     case _ => userService.create(User(username = "User123")) 
    } 
+0

Danke, ich habe es zuerst mit flatMap implated, aber mein Beispiel hier ist sehr vereinfacht im Vergleich zu meiner ursprünglichen Methode, ich hatte viele verschachtelte flatMaps/Karten, deshalb habe ich beschlossen, es mit dem Verständnis umschreiben – Teimuraz

+0

Es macht Sinn :) –