When using Playframework, I am sometimes faced with this situation :
def myFunction:Future[String] = {
// Do some stuff
}
myFunction.onComplete {
case Success(myString) => // Du Stuff
case Failure(error) => // Error handling
}
But as stated in the Scala doc, Future.onComplete
returns a Unit.
How can I use those in Playframework when Action
functions for example expect a SimpleResult
? What are the best practices for handling Futures?
EDIT : I should add, I am using Play-2.2.x branch which has traded the Play Future for the Scala Future.
Future represents a result of an asynchronous computation that may or may not be available yet. When we create a new Future, Scala spawns a new thread and executes its code. Once the execution is finished, the result of the computation (value or exception) will be assigned to the Future.
Play is rock-solid and used by hundreds of thousands of Java and Scala developers every month. Play is still extremely relevant to today's application and web development and has a passionate and very capable community around it ensuring that it has many good years left.
This course enables developers to write non-blocking and asynchronous code using Scala. You'll learn how to use Scala Futures for writing async code. It covers how actor model can be leveraged to write an asynchronous and message based application.
Scala will not magically make synchronous code asynchronous, but it will provide you all you need to write fully a asynchronous one (Futures/Promises, Actors, Streams, ...). Being asynchronous does not mean being single threaded, it means you keep doing useful thinks while waiting for replies.
You can use Async
:
def index = Action{
val myFunction:Future[Option[String]] = //
Async{
myFunction.map{
case Some(x) => Ok(x)
case None => InternalServerError
}
}
}
Basically you tell play that: Whenever myFunction
is evaluated, return the result back to User. The trick here is to map
on the Future
content instead of using a callback, this lets you operate on the result.
The wonderful part is that it is still asynchronous. In the sense that the http request thread evaluation index will not get blocked.
Some documentation on it here.
Play (at least in 2.1) adds an extend1
method that you might find useful:
def myFunction: Future[String] = ???
myFunction.extend1 {
case Redeemed(v) => s"Got result string: $v"
case Thrown(t) => s"Got throwable: ${t.getMessage}"
} // : Future[String]
It's probably better, however, to have computations that fail explicitly, using e.g. Option
(as Jatin demonstrates), Either
, or scalaz.\/
.
Edit: as you point out, PlayPromise
is deprecated in Play 2.2. It's trivial to emulate its behaviour with the Future
methods, for instance:
myFunction.map(v => s"Got result string: $v").recover {
case t => s"Got throwable: ${t.getMessage}"
}
If you wanted to recreate the extend1
syntax it would be simple to add the appropriate implicits.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With