Our Futures Are Better Than Google’s Promises

By on February 27, 2018 - 8 Minutes

Asynchronous processes are very common in software engineering. In mobile development you’ll find them in a variety of situations, from network requests to background tasks. There are common design patterns that make the management of asynchronous tasks less painful, but they’ve not always have been around, especially the ones that require specific features in the language used.


Blocks haven’t always been available. Apple added them to a non-standard extension on the Clang compiler back in ~2010. Before, programmers had to use design patterns as the Observer/Listener, Delegate or KVO (KeyValueObserving), among others. Today we can still find many of these patterns in Cocoa, which were implemented many years ago.

For example, this would be an old fashioned way of doing async requests in Cocoa:

Once blocks were added, programmers quickly adopted them and they soon became a standard way to organize code. Hundreds of lines were saved by using blocks and their usage was widespread: they even reached past their initial purpose and could be found anywhere, not only as a “completionBlock:” in an obj-c method, but even as properties in view classes to manage user events, for example. This however, is a bad practice as retain cycles can easily happen, and code readability and maintainability decreased tremendously.

Following the code example from above, here we could find a block-based implementation for an async request:

We should also not forget about the well-known callback hell, where we start nesting completion blocks and create a death pyramid.


At Mobile Jazz we decided to stop using completion blocks and use something based on the idea of Promises or Futures. A Future (or Promise) is a container for a value that might or might not yet be defined, but eventually will be. Essentially, it’s a wrapper for a completion block. Futures are single use and have a very simple interface to set and retrieve values or errors.

By using using Futures, methods now won’t use completion blocks as parameters but instead, return Future objects. Additionally, as we now have an object instead of a raw block, we can extend the implementation of the Future class and add some functional programming methods such as map, filter, flatMap, recover, etc… adding capabilities to create chains of futures to manage, convert, and edit a value that is or isn’t defined.

There are many open source libraries for Futures or Promises, but we decided to create our own in order to achieve the class interface that suited most of our projects and code conventions. All in all, a Promise/Future is a simple wrapper and there’s not too much happening inside other than a couple of conditions.

This is how our first library MJFuture for Objective-c was born. Feel free to check our repository or test it via CocoaPods:

When Swift arrived, we of course wanted to use MJFuture in Swift projects. And so we implemented a pure Swift version, escaping from the Objective-C in order to gain speed from the efficiency of Swift. We called it Future, no more prefixes. The public interface is largely the same as MJFuture, with some enhancements to make it more Swift-ish.

With these two implementations, we can now forget about completion blocks or closures forever! Our projects are mostly based on clean architecture and we are now returning Future instances starting from the lower layers of our app, like base storage or network calls, and using functional programming to manipulate the data and create future chains that reach the last stage the user interface.

Reactive Futures

Wait, isn’t this reactive architecture? Signals and stuff? The answer is no. Futures have a single use, and then a new instance must be created. Here, we’re not creating a reactive application, but instead making developer-friendly application with readable code base and flexible architecture. We have however, added support for a reactive usage (reusable futures) just for the few occasions we’ve required a reactive future chain.

Observer Pattern

In an effort to replace the listener/observer pattern, we had to find a way to enable us to have multiple observers for the same Future value. While we could indeed chain multiple .then() closures one after the other add an observer to the last item in the chain, but instead we created something we called a FutureHub.

A Hub is a class that features a main Future and can create or register additional Future instances that will react to the main Future. The Hub observes the main future and when updates are received, it is notifying all other registered Futures. It’s perfect for combining with the reactive Future feature.

Making the Async, Sync

One of the main advantages of working with Futures is it’s feature to retrieve the value or error synchronously. This allow the developer to avoid nesting calls inside the .then() closures and just write sync code on the same indentation. Obviously, this code must be called from a background thread otherwise the UI thread might block.

In the next example, we find a snippet related to async nested calls. Even working with Futures, we can see some callback hell:

However, once switching code to sync futures, the code readability is increased tremendously:

And What About Google Promises?

A couple of weeks ago Google unveiled its new library Promises, bringing a whole new level of efficiency and usability of Promises to Swift and Objective-C.

When we gave it a look we couldn’t be more surprised. The public interface is exactly the same as our Futures, except for some minor naming conventions. They call it Promise, we call it Future, they call it .fulfill(), we call it .set(), they call it .then(), we call it .then()… wait that’s the same. We even found that our Future contained all of the same methods from Promises, and more including .map(), .flatMap(), .mapError(), .zip(), .collapse()
and FutureHub.

Both libraries and their interfaces are very similar. So we thought this was a great opportunity to learn from Google and improve our Futures based on how Promises work, retaining in our minds the original reasons as to why we created Futures in the first place – to enhance our programming experience by having a highly usable and flexible alternative to Blocks.

Here’s an example between using our Futures and Google’s Promises:

It’s true that Google’s Promises had two major advantages:

  1. The same library is used for both Swift and Objective-C
  2. Performance-wise, Promises showed great results in benchmarks compared to other similar libraries.

Or is that true?

MJFutures (our Obj-C library) can already be used in both Swift and Objective-C based projects. And if you’re mixing Obj-C and Swift, there are methods to convert MJFutures (Obj-C) to Future (Swift).

Performance is another topic. Who could beat Google on performance? They have the best engineers and if they announce new revolutionary library, it’s because it’s done something you’d always wanted, or it’s faster than any other existing solution.

Pretty chuffed with our libraries performance, we thought we’d give it a test. How? We downloaded the Google’s Promises repository, copied their tests and replaced the “Promise” by “Future”. That simple. Just a couple of name changes and we had a full performance test ready to run:

  • Grand Central Dispatch (GCD)
  • Google Promises
  • Futures (Swift)
  • MJFutures (Objective-C)

Find here the tests here.

The results couldn’t be more surprising. Both our Future and MJFuture outperformed Google Promises in every single test. Initially, we couldn’t believe it, were we doing something wrong? We double, triple,even quadruple checked and no, it was crystal clear: our implementation is faster than Google’s.

Using a serial queue, results show the average time of 10,000 single, double and triple chains of dispatch async, Future, MJFuture and Promise:

Results shown in seconds.

Using a concurrent queue, results show the average time of 10,0000 concurrent operations over dispatch async, Future, MJFuture and Promise:

So how is our library faster than Google’s? Well, probably because we have achieved two different things:

  1. Google’s Promises is a library implemented for both Swift and Objective-C and has been optimized to work best in this context. It’s public interface is great in both Swift and Objective-C and its performance is better than any other known library.
  2. Future and MJFuture are libraries that have been implemented to be efficient in Swift and Objective-C respectively. Whilst you can use MJFuture in Swift, but it’s interface isn’t as nice as Google’s Promises. Therefore, performance is exchanged for exclusivity on each platform.

While coding the Future and MJFuture, we always try to keep it simple, nice, lean and fast. There’s no magic, and everyone should be able to read the code and understand what’s going on.

In conclusion, what started as an initiative to run away from completion blocks lead us to implement a library that works tremendously well. This is the first time we are opening it to the community and sharing our code, open source and free to use.

Read the comments
Joan Martin
Starting with mathematics, continuing with a computer science masters degree and working on mobile development during the past 8 years, Joan is a proficient software engineer. Motivated by great projects and an awesome team, Joan is currently leading the mobile team at Mobile Jazz and enjoying the MJ philosophy at its best.

Want to receive more insightful articles like this? Subscribe here.

By submitting your information you agree to our Privacy Policy