We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

Login or register
to apply for this job!

Login or register to start contributing with an article!

Login or register
to see more jobs from this company!

Login or register
to boost this post!

Show some love to the author of this blog by giving their post some rocket fuel 🚀.

Login or register to search for your ideal job!

Login or register to start working on this issue!

Engineers who find a new job through Functional Works average a 15% increase in salary 🚀

Blog hero image

Scala Future blocks and Future's methods: What to use...and when!

Surya Thamminaina 16 June, 2018 | 3 min read

Introduction

One of the rich and beautiful features provided by Scala programming language is the Scala Future. For the beginners to introduce futures simply, the Future allows you to write a code snippet which completes and produces the response sometime in the future.

Well, although Futures allow you to write rich, non-blocking and concurrent code, it is very much important to know how to use Futures in different styles (or in other words, in different contexts) to make an effective code.

In this post, I'm going to discuss How to write an effective Scala Future in different use cases.

During my scala journey, I have observed how many people are quite habituated or sometimes mistakenly implement futures using just a Future() but unfortunately, this may not result an effective future all the time.

Future.apply() or Future()

Future( ... 
<some_code>
...
)

This style of code compiles well, gives you a future result. But... this one perhaps creates a separate thread to execute the block asynchronously. This comes at the cost of additional memory allocations, context switches, and synchronization among threads. An individual result may be fractionally slower when executed asynchronously.

However, Future blocks are the best fit to use when you need to process a network call (can be an external service), when you want to interact with database or any other scenario where the block/function needs some time to process and come back.

Future.successful()

Future.successful(...
 <some_code>
...
)

And now, In the other hand we many times encounter some situations where we need to send some default future results or already processed results as a future result. Few such instances can be when you want to send your custom error response object (as a successful response) instead of throwing the exact error back to the rest client when something wrong happens with your rest api.

In such scenarios where the value has been already computed and should go back as a future value, you should not go for a Future block (because of it's overhead as discussed above) rather,Future.successful should be the right fit there as runs with in the same thread and wraps the response with a Future

def getSupportRepresentativeEmail(id: String) = Action.async { request =>
if(!"".equals(id) && id.length == 10L) {
 val result: Future[SupportRepresent] = getSupportRepresent(id)
result.map(representativeInfo => Ok(representativeInfo.emailId))
}
else
Future.successful(Ok("support@company.com"))
}

But point to be noted here is, The Future.successful runs on the current thread and blocks the current thread until it completes. So it is most appropriate to use Future.successful with a literal value rather using it contact a database server or any other complex operations like that

Future.failed()

Like Future.successful, the Future.failed also run on the current thread and wraps the exception with a future.

So, When you encounter any situation, where you need to throw back a direct exception from the code with in the future instead of any further processing, Future.failed would be the right fit there!. However in the situations where you don't know which exception to throw back and exception may actually occur sometime in future, that piece of code can be moved with in the Future block.Future.failed takes any Throwable type object.

Example Situation: In the same above example, If you want to throw back exception instead of sending the default support email when request sends an invalid id, you can use the Future.failed as shown below

def getSupportRepresentativeEmail(id: String) = Action.async { request =>
if(!"".equals(id) && id.length == 10L) {
 val result: Future[SupportRepresent] = getSupportRepresent(id)
result.map(representativeInfo => Ok(representativeInfo.emailId))
}
else
Future.failed(new IllegalArgumentException("Invalid Support Representative Id."))
}

Conclusion

  1. Use Future.apply() or simply Future() (i.e., Future block) in the situations where something to be done asynchronously that can complete sometime in future and may deal with some time consuming operations such as network calls, database operations communicate with one or many other services, processing huge data by consuming multiple cores and etc.
  2. Use Future.successful when a literal or already computed value to be passed back as a successful future response
  3. Use Future.failed when a known and literal exception to be thrown back without performing any further actions with in the future.

Best of luck for your Future endeavors! :)

Author's avatar
Surya Thamminaina
- Scala Developer - Functional Programming Enthusiastic
    Scala

Related Issues

viebel / klipse-clj
viebel / klipse-clj
  • Open
  • 0
  • 0
  • Intermediate
  • Clojure
viebel / klipse
  • Open
  • 0
  • 0
  • Intermediate
  • Clojure
viebel / klipse
  • 1
  • 0
  • Intermediate
  • Clojure
viebel / klipse
  • Started
  • 0
  • 1
  • Intermediate
  • Clojure
  • $80
viebel / klipse
  • Open
  • 0
  • 0
  • Advanced
  • Clojure
  • $80
viebel / klipse
  • Started
  • 0
  • 2
  • Advanced
  • Clojure
  • $180
viebel / klipse
  • Started
  • 0
  • 1
  • Intermediate
  • Clojure
viebel / klipse
  • 1
  • 1
  • Advanced
  • Clojure
  • $300

Get hired!

Sign up now and apply for roles at companies that interest you.

Engineers who find a new job through Functional Works average a 15% increase in salary.

Start with GithubStart with Stack OverflowStart with Email