lorenzocastillo
lorenzocastillo

Reputation: 1025

Convert Await.result into for/yield

I'm looking for a way to turn the following into a non-blocking call:

val (greeting, name) = 
    if (someCondition) { 
        ("Welcome", Option(""))
    } else { 
        var name = Await.result(userClient.getName(arg), Duration.Inf)) 
        ("Hi", name)
    }

I'm thinking of doing something along the lines of:

val (greeting, name) = 
    if (someCondition) { 
        ("Welcome", Option(""))
    } else { 
        for {
            name <- userClient.getName(arg)
        }
        yield {
            ("Hi", name) 
        }   
    }

The issue I'm facing is that the for/yield returns a Future[String] to the name tuple for else statement, but returns a Option[String] for the if statement. I need them both to return an Option. In other words, I need to resolve the future. If I pull the name out of the yield, then it won't be in the same scope and the compiler can't figure out that there's a name in the for.

If this can be done without a for/yield that's okay. Just don't want it to be a blocking call.

Upvotes: 1

Views: 120

Answers (1)

Alec
Alec

Reputation: 32319

The best you can do is

val (greeting, name): (String, Future[Option[String]]) = if (someCondition) { 
  ("Welcome", Future.successful(Some("")))
} else {
  ("Hi", userClient.getName(arg))
}

You can't convert a Future[Option[String]] into Option[Future[String]] without awaiting the Future; an Option[Future[String]] knows upfront if it is Some or None while Future[Option[String]] doesn't.

In this case, there is no need for a for comprehension.

Upvotes: 1

Related Questions