Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usage of Scala Future in Playframework?

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.

like image 810
i.am.michiel Avatar asked Aug 06 '13 10:08

i.am.michiel


People also ask

How do futures work in Scala?

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.

Is Play framework still used?

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.

Does Scala support asynchronous programming?

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.

Is Scala asynchronous?

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.


2 Answers

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.

like image 183
Jatin Avatar answered Sep 28 '22 07:09

Jatin


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.

like image 29
Hugh Avatar answered Sep 28 '22 09:09

Hugh