Browse files

controlling flow with scala futures

  • Loading branch information...
1 parent b421536 commit 7aa14d92a72302fdc51340178cc4169264a0ee6e @Srirangan committed Jan 15, 2013
Showing with 180 additions and 4 deletions.
  1. +10 −4 app/views/index.scala.html
  2. +170 −0 public/posts/2013-01-controlling-flow-with-scala-futures.html
View
14 app/views/index.scala.html
@@ -3,10 +3,10 @@
<div class='span9'>
<ul class="unstyled">
<li>
- <a href="http://www.scalacommunity.com/post_the_quest_to_become_a_scala_developer_1357932622644">
- The quest to become a Scala developer
+ <a href="/2013-01-controlling-flow-with-scala-futures">
+ Controlling flow with Scala Futures
</a>
- <small>2013-01-11</small>
+ <small>2013-01-14</small>
</li>
<li>
<a href="/2013-01-first-steps-with-scala-futures">
@@ -15,7 +15,13 @@
<small>2013-01-09</small>
</li>
<li>
- <strong><em>Happy New Year! =D</em></strong>
+ <a href="http://www.scalacommunity.com/post_the_quest_to_become_a_scala_developer_1357932622644">
+ The quest to become a Scala developer
+ </a>
+ <small>2013-01-11</small>
+ </li>
+ <li>
+ Happy New Year!
<small>2013-01-01</small>
</li>
<li>
View
170 public/posts/2013-01-controlling-flow-with-scala-futures.html
@@ -0,0 +1,170 @@
+<h2>Controlling flow with Scala Futures</h2>
+
+<div class="entry-content">
+ <blockquote>
+ This post is a continuation of <a href="/2013-01-first-steps-with-scala-futures">First steps with `futures` in Scala</a> especially if
+ you're unfamiliar with <code>Futures</code> introduced in Scala 2.10.
+ <small>Sri</small>
+ </blockquote>
+ <p>Composing units of code that execute asynchronously | concurrently | in-parallel is now trivial and elegant.</p>
+ <p>Real-world systems need to enforce some form of control-flow. Asynchronous control flow.</p>
+ <p>This can get tricky. Especially if you must avoid spaghetti nested code.</p>
+ <p>Thoughtfully Scala introduces a few constructs to avoid the mess.</p>
+ <hr/>
+ <p>Futures may fail. They may throw exceptions. Thus far we were trapping <code>onFailure</code>.</p>
+ <p>In the example below, we <code>recover</code> from an exception and return a string value.</p>
+ <pre>
+ // Sometimes we need recover from an exception with a value
+ // lets `recover` from an exception with a fallback val 'Infinity'
+
+ val tryDivideByZeroAgain = future {
+ Thread.sleep(1000)
+ 1 / 0
+ } recover {
+ case e: ArithmeticException => "Infinity"
+ }
+
+ tryDivideByZeroAgain onSuccess {
+ case e => Console.println(e)
+ }
+
+ tryDivideByZeroAgain onFailure {
+ case e => Console.println(e)
+ }
+
+ Console.println("Try dividing by zero, recover from exception..")
+
+ Thread.sleep(2000)
+
+ // output
+ // Try dividing by zero, recover from exception..
+ // Infinity
+ </pre>
+ <hr/>
+ <p>Moving on, a similar example but we don't want to recover directly with an expression / value.</p>
+ <p>Instead we want a failing future to <code>fallbackTo</code> another asynchronous future.</p>
+ <pre>
+ // Or maybe future f1 must fallback to future f2?
+
+ val f1 = future {
+ Thread.sleep(500)
+ 1 / 0
+ }
+
+ val f2 = future {
+ Thread.sleep(500)
+ "Infinity"
+ }
+
+ f1 fallbackTo f2 onSuccess {
+ case v => Console.println(v)
+ }
+
+ Console.println("Try dividing by zero, fallback to another future..")
+
+ Thread.sleep(2000)
+
+ // output
+ // Try dividing by zero, fallback to another future..
+ // Infinity
+ </pre>
+ <hr/>
+ <p>With <code>andThen</code> we can execute a series of futures and explicitly define the execution order.</p>
+ <pre>
+ // the for {} construct lets us execute multiple futures in parallel
+ // to serially execute futures in specific orders, we use `andThen`
+ // andThen ensures execution orders in what would otherwise be random
+
+ val whamBamThankYouMaam = future {
+ Thread.sleep(500)
+ Console.println("Wham!")
+ } andThen {
+ case _ => {
+ Thread.sleep(500)
+ Console.println("Bam!")
+ }
+ } andThen {
+ case _ => {
+ Thread.sleep(500)
+ Console.println("Thank you ma'am!")
+ }
+ }
+
+ Console.println("Will you score?")
+
+ Thread.sleep(2000)
+
+ // output
+ //
+ // Will you score?
+ // Wham!
+ // Bam!
+ // Thank you ma'am!
+ </pre>
+ <hr/>
+ <p>Everything about Scala is type safe. What we have seen of futures, so far, isn't. To ensure futures return results of type T, we use <code>promises</code>.
+ </p>
+ <pre>
+ // `promises` can be used to compose type safe futures
+
+ val willYouMarryMe = promise[Boolean]
+
+ willYouMarryMe.future onSuccess {
+ case yes => Console.println("Yes! :D")
+ }
+
+ willYouMarryMe.future onFailure {
+ case no => Console.println("No :(")
+ }
+
+ future {
+ Thread.sleep(1000)
+ if (new Random().nextBoolean())
+ willYouMarryMe success true // try passing non boolean value here
+ else
+ willYouMarryMe failure new Exception
+ }
+
+ Console.println("Will you marry me?")
+
+ Thread.sleep(2000)
+
+ // output
+ //
+ // Will you marry me?
+ // Yes! :D | No :(
+ </pre>
+ <hr/>
+ <p>Like all futures, <code>promise.future</code> can only be complete once. Thus multiple asynchronous block that <code>tryComplete</code> a promise.</p>
+ <pre>
+ // Two asynchronous blocks `tryComplete` a promise
+
+ val whoWonTheRace = promise[String]
+
+ whoWonTheRace.future onSuccess {
+ case name => Console.println(name + " wins")
+ }
+
+ future {
+ Thread.sleep(new Random().nextInt(500))
+ whoWonTheRace trySuccess "x"
+ }
+
+ future {
+ Thread.sleep(new Random().nextInt(500))
+ whoWonTheRace trySuccess "y"
+ }
+
+ Console.println("Who won the race?")
+
+ Thread.sleep(1000)
+
+ // output
+ //
+ // Who won the race?
+ // x wins | y wins
+ </pre>
+ <p>Methods available here are <code>tryComplete</code>, <code>trySuccess</code> and <code>tryFailure</code></p>
+ <hr/>
+ <p>For further reading check out <a href="http://docs.scala-lang.org/overviews/core/futures.html">Futures and Promises</a> on Scala Docs.</p>
+</div>

0 comments on commit 7aa14d9

Please sign in to comment.