Reputation: 9335
In my method1, I need to call another method2 asynchronously, which returns Option (result1). Than, if result1 is empty, I need to call another method3 asynchronously, but if result1 is NOT empty, I just need to return it.
Here is the method:
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
}
Question is:
Future.successful(foundUser)
- is this approach correct in the code above? Does this line create asynchronous call? If so, how to avoid it? I've already fetched foundUser asynchronously, and I don't want to make additional async call just to return already fetched value.
Upvotes: 5
Views: 851
Reputation: 149636
Future.successful
doesn't queue an additional function on the provided ExecutionContext
. It simply uses a Promise[T]
to create a completed 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
As a side note, you can reduce the amount of boilerplate using Option.fold
:
def signIn(username: String): Future[User] =
userService
.findByUsername(username)
.flatMap(_.fold(userService.create(User(username = "User123")))(Future.successful(_))
Upvotes: 4
Reputation: 53869
@Yuval Itzchakov answered your question, but as a side note, you may want to use flatMap
with pattern matching directly in your case. I personnally find it more readable:
def signIn(username: String): Future[User] =
userService.findByUsername(username)
.flatMap {
case Some(user) => Future.successful(user)
case _ => userService.create(User(username = "User123"))
}
Upvotes: 1