Skip to content

ykyouhei/then

Β 
Β 

Repository files navigation

Then

then

Language: Swift 2 and 3 Platform: iOS 8+ Carthage compatible Cocoapods compatible Build Status codebeat badge Join the chat at https://gitter.im/s4cha/then License: MIT Release version

Reason - Example - Installation

fetchUserId().then { id in
    print("UserID : \(id)")
}.onError { e in
    print("An error occured : \(e)")
}.finally {
    print("Everything is Done :)")
}

Swift Version

Swift 2 -> version 1.4.2
Swift 3 -> version 2.0.2

Why

Because async code is hard to write, hard to read, hard to reason about.
A pain to maintain

How

By using a then keyword that enables you to write aSync code that reads like an English sentence
Async code is now concise, flexible and maintainable ❀️

What

  • Based on the popular Promise/Future concept
  • Lightweight (1 file ~100lines)
  • Pure Swift
  • No magic involved
  • Strongly Typed
  • Chainable

Example

Before

fetchUserId({ id in
    fetchUserNameFromId(id, success: { name in
        fetchUserFollowStatusFromName(name, success: { isFollowed in
            // The three calls in a row succeeded YAY!
            reloadList()
        }, failure: { error in
            // Fetching user ID failed
            reloadList()
        })
    }, failure: { error in
        // Fetching user name failed
        reloadList()
    })
}) {  error in
    // Fetching user follow status failed
    reloadList()
}
πŸ™‰πŸ™ˆπŸ™Š#callbackHell

After

fetchUserId()
    .then(fetchUserNameFromId)
    .then(fetchUserFollowStatusFromName)
    .then(updateFollowStatus)
    .onError(showErrorPopup)
    .finally(reloadList)

πŸŽ‰πŸŽ‰πŸŽ‰

Going further πŸ€“

fetchUserId().then { id in
    print("UserID : \(id)")
}.onError { e in
    print("An error occured : \(e)")
}.finally {
    print("Everything is Done :)")
}

If we want this to be maintainable, it should read like an English sentence
We can do this by extracting our blocks into separate functions:

fetchUserId()
    .then(printUserID)
    .onError(showErrorPopup)
    .finally(reloadList)

This is now concise, flexible, maintainable, and it reads like an English sentence <3
Mental sanity saved // #goodbyeCallbackHell

Writing your own Promise πŸ’ͺ

Wondering what fetchUserId() is?
It is a simple function that returns a strongly typed promise :

func fetchUserId() -> Promise<Int> {
    return Promise { resolve, reject in
        print("fetching user Id ...")
        wait { resolve(1234) }
    }
}

Here you would typically replace the dummy wait function by your network request <3

Progress

As for then and onError, you can also call a progress block for things like uploading an avatar for example.

uploadAvatar().progress { p in
  // Here update progressView for example
}
.then(doSomething)
.onError(showErrorPopup)
.finally(doSomething)

Registering a block for later

Calling then starts a promise if it is not already started. In some cases, we only want to register some code for later. For instance, in the case of JSON to Swift model parsing, we often want to attach parsing blocks to JSON promises, but without starting them.

In order to do that we need to use registerThen instead. It's the exact same thing as then without starting the promise right away.

let fetchUsers:Promise<[User]> = fetchUsersJSON().registerThen(parseUsersJSON)

// Here promise is not launched yet \o/

// later...
fetchUsers.then { users in
    // YAY
}

Bonus : whenAll

whenAll calls you back when all the promises passed are fullfiled :

whenAll(fetchUsersA(),fetchUsersB(), fetchUsersC()).then { allUsers in
  // All the promises came back
}

Returning a rejecting promise

Oftetimes we need to return a rejecting promise as such :

return Promise { _, reject in
  reject(anError)
}

This can be written with the following shortcut :

return Promise.reject(error:anError)

Installation

Cocoapods

pod 'thenPromise'
use_frameworks!

Carthage

github "freshOS/then"

Manually

Simply Copy and Paste Promise.swift in your Xcode Project :) https://github.com/freshOS/then/blob/master/Code/then/Promise.swift

As A Framework

Grab this repository and build the Framework target on the example project. Then Link against this framework.

Contributors

S4cha, YannickDot, Damien, piterlouis

Other repos ❀️

then is part of a series of lightweight libraries aiming to make developing iOS Apps a breeze:

About

Promises Library for Swift 🎬

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 95.0%
  • Objective-C 2.8%
  • Ruby 2.2%