Futures & Promises

What’s the difference between a Future and a Promise?

The easiest way to think about it, in my opinion, is like this:

  • Promise is something you make to someone else.
  • In the Future you may choose to resolve that promise, or reject it.

If we use the above definition, Futures & Promises become two sides of the same coin. A promise gets constructed, then returned as a future, where it can be used to extract information at a later point.

Futures are basically representing a value in the future. The underlying value can be for example a result and it should have one of the following states:

  • pending – no value yet, waiting for it…
  • fulfilled – success, now the result has a value
  • rejected – failed with an error

Problem

Are you familiar with this code?


  fetchJSON(fromURL: "someURL") { (response, results, error) in
            switch response {
            case .success:
                fetchUserData(for: results) { (response, results, error) in
                    switch response {
                    case .success:
                        loginUser(user: results) { (response, results, error) in
                            switch response {
                            case .success:
                                // finialy all of the callbacks are finished
                                print("Handle logic here")
                            case .fail:
                                print(error)
                            }
                        }
                    case .fail:
                        print(error)
                    }
                }
            case .fail:
                print(error)
            }
        }
        

In the example code we have three nested functions that gets called one after another. First function fetchJSON returns JSON data, then we pass that JSON data into the second function to fetch specific info for a user fetchUserData and after that, we call the third function to login the current user loginUser

This is called a callback hell or pyramid of doom 🔥. This is not clean code and if you want to write clean structured code then Promises are the best choice for this type of problems.

Solution

create Promise

In this tutorial, we are using PromiseKit library https://github.com/mxcl/PromiseKit

First, We will wrap all three functions to return a Promise

func promiseFetchJSON() -> Promise<[String: Any]> {
        return Promise<[String: Any]> { seal in
            fetchJSON(fromURL: "someURL", completion: { (response, results, error) in
                switch response {
                case .success:
                    seal.fulfill(results)
                case .fail:
                    seal.reject(error)
                }
            })
        }
    }
func promiseFetchUserData(user: [String: Any]) -> Promise<User> {
        return Promise<User> { seal in
            fetchUserData(for: user, completion: { (response, results, error) in
                switch response {
                case .success:
                    seal.fulfill(results)
                case .fail:
                    seal.reject(error)
                }
            })
        }
    }
func promiseLoginUser(user: User) -> Promise<Bool> {
        return Promise<Bool> { seal in
            loginUser(user: user, completion: { (response, resolts, error) in
                switch response {
                case .success:
                    seal.fulfill(true)
                case .fail:
                    seal.reject(error)
                }
            })
        }
    }

Using Promises in real life

firstly {
    promiseFetchJSON()
}.then { (json)  in
    promiseFetchUserData(user: json)
}.then { (user) in
    promiseLoginUser(user: user)
}.ensure {
    // something that should happen whatever the outcome        
}.done { (success) in
    // all promises are resolved
    // handle final logic here
}.catch { (error) in
    // handle error here
}

firstly is just a syntax to make code more readable and in this closure, we pass the first promise function promiseFetchJSON()

then is another way to structure completion handlers that help us to easily understand asynchronous operations. If we return a promise in then closure, then the next then will wait for that promise before continuing

The chain ends in the done closure and that means that all of the promises are fulfilled successfully.

A nature, universe, science, music, love lover

Leave a Reply

Your email address will not be published. Required fields are marked *

Bitnami