Difference Await.ready and Await.result
Asked Answered
S

3

49

I know this is quite an open ended question and I apologize.

I can see that Await.ready returns Awaitable.type while Await.result returns T but I still confuse them.

What are the difference between the two?

Is one blocking and the other one non-blocking?

Selffulfillment answered 15/12, 2016 at 17:43 Comment(0)
A
52

They both block until the future completes, the difference is just their return type.

The difference is useful when your Future throws exceptions:

def a = Future { Thread.sleep(2000); 100 }
def b = Future { Thread.sleep(2000); throw new NullPointerException }

Await.ready(a, Duration.Inf) // Future(Success(100))    
Await.ready(b, Duration.Inf) // Future(Failure(java.lang.NullPointerException))

Await.result(a, Duration.Inf) // 100
Await.result(b, Duration.Inf) // crash with java.lang.NullPointerException
Annorah answered 15/12, 2016 at 18:15 Comment(1)
If I'm not mistaken, Await.ready will not return the Try directly but you have to extract it from the future first via Await.ready(a, d).value.get.Buckling
B
16

Both are blocking for at most the given Duration. However, Await.result tries to return the future result right away and throws an exception if the future failed while Await.ready returns the completed future from which the result (Success or Failure) can safely be extracted via the value property.

The latter is very handy when you have to deal with a timeout as well:

val future = Future { Thread.sleep(Random.nextInt(2000)); 123 }

Try(Await.ready(future, 1.second)) match {
    case Success(f) => f.value.get match {
      case Success(res) => // handle future success 
      case Failure(e) => // handle future failure
    }
    case Failure(_) => // handle timeout
}

When using Await.result, the timeout exception and exceptions from failing futures are "mixed up".

Try(Await.result(future, 1.second)) match {
    case Success(res) => // we can deal with the result directly
    case Failure(e) => // but we might have to figure out if a timeout happened
}
Buckling answered 8/4, 2019 at 19:49 Comment(0)
E
3

In general, both are blocking.

The difference is that Await.ready is blocking until the Future has finished (successful or failed) in given time.

The only one difference is that ready blocks until the Awaitable is ready and the result does yield the result type T.

Postscriptum: In practice, if you want to perform some actions like error checking or logging you would take Await.ready(...) if you want to compose the result and throw an error if something goes wrong take Await.result(...).

As rule of thumb - try to avoid Await.

Elyot answered 15/12, 2016 at 18:9 Comment(2)
Why do you say to avoid Await? What should be used instead? Thanks.Maidstone
@LarsSkaug You should preferably return the actual future and process the result... e.g. future.flatMap(result => { // do something }) Or whatever your preferred logic is to process the result The problem with Await is that it will block whereas the above logic will allow the thread to continue on. I'd argue Await may make sense if you don't care about blocking and just want code that is easy to follow.Fibrin

© 2022 - 2024 — McMap. All rights reserved.