2016-08-22 2 views
4

В моем методе1 мне нужно асинхронно вызывать другой метод2, который возвращает Option (result1). Чем, если result1 пуст, мне нужно вызвать другой метод3 асинхронно, но если result1 не пуст, мне просто нужно его вернуть.Scala Future - для понимания, синхронизации микширования и async

Вот метод:

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 
    } 

Вопрос:

Future.successful(foundUser) - такой подход правильным в приведенном выше коде? Эта линия создает асинхронный вызов? Если да, то как этого избежать? Я уже выбрал foundUser асинхронно, и я не хочу делать дополнительный асинхронный вызов только для возврата уже полученного значения.

ответ

4

Future.successful не ставит в очередь дополнительную функцию на предоставляемом ExecutionContext. Он просто использует Promise[T] для создания законченной Future[T]:

/** 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 

В качестве примечания, вы можете уменьшить количество шаблонного использования Option.fold:

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

спасибо @Yuval Itzchakov – Teimuraz

+0

кстати, если я пишу будущее {foundUser} вместо Future.successful (foundUser), она выполняется асинхронно, не так ли? – Teimuraz

+0

@moreo Да, это вызовет очередность функции в 'ExecutionContext'. –

1

@Yuval Itzchakov ответил на ваш вопрос, но как обратите внимание, вы можете использовать flatMap с шаблоном, соответствующим прямому в вашем случае. Я Personnally найти его более читабельным:

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

Спасибо, я сначала применил flatMap, но мой пример здесь очень упрощен по сравнению с моим оригинальным методом, у меня было много вложенных карт/карт, поэтому я решил переписать его для понимания. – Teimuraz

+0

Это делает смысл :) –

Смежные вопросы