All Projects → DimaMishchenko → Easyfutures

DimaMishchenko / Easyfutures

Licence: mit
Easy Swift Futures & Promises.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Easyfutures

Promis
The easiest Future and Promises framework in Swift. No magic. No boilerplate.
Stars: ✭ 110 (+175%)
Mutual labels:  promises, futures
Q
A platform-independent promise library for C++, implementing asynchronous continuations.
Stars: ✭ 179 (+347.5%)
Mutual labels:  promises, futures
Promise
Promise / Future library for Go
Stars: ✭ 149 (+272.5%)
Mutual labels:  promises, futures
Swiftcoroutine
Swift coroutines for iOS, macOS and Linux.
Stars: ✭ 690 (+1625%)
Mutual labels:  promises, futures
Promises
Promises is a modern framework that provides a synchronization construct for Swift and Objective-C.
Stars: ✭ 3,576 (+8840%)
Mutual labels:  promises, futures
Tomorrowland
Lightweight Promises for Swift & Obj-C
Stars: ✭ 106 (+165%)
Mutual labels:  promises, futures
Hydra
⚡️ Lightweight full-featured Promises, Async & Await Library in Swift
Stars: ✭ 1,954 (+4785%)
Mutual labels:  promises, futures
Pinfuture
An Objective-C future implementation that aims to provide maximal type safety
Stars: ✭ 74 (+85%)
Mutual labels:  promises, futures
future.callr
🚀 R package future.callr: A Future API for Parallel Processing using 'callr'
Stars: ✭ 52 (+30%)
Mutual labels:  promises, futures
swift-futures
Demand-driven asynchronous programming in Swift
Stars: ✭ 32 (-20%)
Mutual labels:  promises, futures
Brightfutures
Write great asynchronous code in Swift using futures and promises
Stars: ✭ 1,890 (+4625%)
Mutual labels:  promises, futures
Asynchronous
Implementation-agnostic asynchronous code
Stars: ✭ 13 (-67.5%)
Mutual labels:  promises, futures
Futures
Lightweight promises for iOS, macOS, tvOS, watchOS, and Linux
Stars: ✭ 59 (+47.5%)
Mutual labels:  promises, futures
Lwt
OCaml promises and concurrent I/O
Stars: ✭ 505 (+1162.5%)
Mutual labels:  promises, futures
Future
🚀 R package: future: Unified Parallel and Distributed Processing in R for Everyone
Stars: ✭ 735 (+1737.5%)
Mutual labels:  promises, futures
Tk Listen
A library that allows to listen network sockets with proper resource limits and error handling
Stars: ✭ 27 (-32.5%)
Mutual labels:  futures
Native Promise Only
A polyfill for native ES6 Promises as close as possible (no extensions) to the strict spec definitions.
Stars: ✭ 708 (+1670%)
Mutual labels:  promises
Restclient
🦄 Simple HTTP and REST client for Unity based on Promises, also supports Callbacks! 🎮
Stars: ✭ 675 (+1587.5%)
Mutual labels:  promises
Bluebird Api
Bluebird compatible API on top of native promises.
Stars: ✭ 36 (-10%)
Mutual labels:  promises
Rust Mdo Future
Zero-cost futures support for rust-mdo
Stars: ✭ 14 (-65%)
Mutual labels:  futures

❗️Archived now❗️

Since Apple released Combine framework, I decide to archive this repo. You still can use this repo as an example of Future/Promise implementation in Swift.

EasyFutures

Swift 4.2 CocoaPods compatible Build Status codecov.io Packagist

Swift implementation of Futures & Promises. You can read more about Futures & Promises in Wikipedia: https://en.wikipedia.org/wiki/Futures_and_promises.

EasyFutures is:

Documentation

  • Full documentation and more examples you can find in Playground (to use playground you should open it in EasyFutures.xcodeproj and build EasyFutures framework).
  • Wiki (full documentation and all examples).
  • Unit tests.
  • Examples section.

Requirements

  • iOS 9.0+

Installation

CocoaPods:

  • Add the following line to your Podfile:
pod 'EasyFutures'

#for swift less than 4.2 use:
pod 'EasyFutures', '~> 1.1.0'
  • Add use_frameworks! to your Podfile.
  • Run pod install.
  • Add to files:
import EasyFutures

Examples

Traditional way to write asynchronous code:

func loadChatRoom(_ completion: (_ chat: Chat?, _ error: Error?) -> Void) {}
func loadUser(id: String, _ completion: (_ user: User?, _ error: Error?) -> Void) {}

loadChatRoom { chat, error in
    if let chat = chat {
        loadUser(id: chat.ownerId) { user, error in
            if let user = user {
                print(user)
                // owner loaded
            } else {
                // handle error
            }
        }
    } else {
        // handle error
    }
}

Same logic but with EasyFutures:

func loadChatRoom() -> Future<Chat>
func loadUser(id: String) -> Future<User> 

loadChatRoom().flatMap({ chat -> Future<User> in
    // loading user
    return loadUser(id: chat.ownerId)
}).onSuccess { user in
    // user loaded
}.onError { error in
    // handle error
}

Future

Future is an object that contains or will contain result which can be value or error. Usually result gets from some asynchronous process. To receive result you can define onComplete, onSuccess, onError callbacks.

func loadData() -> Future<String> 

let future = loadData()

future.onComplete { result in
    switch result {
    case .value(let value):
        // value
    case .error(let error):
        // error
    }
}

future.onSuccess { data in
    // value
}.onError { error in
    // error
}

Promise

The Promises are used to write functions that returns the Futures. The Promise contains the Future instance and can complete it.

func loadData() -> Future<String> {

    // create the promise with String type
    let promise = Promise<String>()

    // check is url valid
    guard let url = URL(string: "https://api.github.com/emojis") else {
        // handle error
        promise.error(ExampleError.invalidUrl)
        return promise.future
    }

    // loading data from url
    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        if let data = data, let string = String(data: data, encoding: .utf8) {
            // return result
            promise.success(string)
        } else {
            // handle error
            promise.error(ExampleError.cantLoadData)
        }
    }
    task.resume()

    // return the future
    return promise.future
}

loadData().onSuccess { data in
    DispatchQueue.main.async {
        self.label.text = data
    }
}.onError { error in
    print(error)
    // handle error
}

Composition

map

Returns the new Future with the result you return to closure or with error if the first Future contains error.

let future = Future<Int>(value: 100)
future.onSuccess { value in
    // value == 100
}

let mapFuture = future.map { value -> String in
    return "\(value) now it's string"
}
mapFuture.onComplete { result in
    switch result {
    case .value(let value):
        print(value) // "100 now it's string""
    case .error(let error):
        // handle error
    }
}

flatMap

Returns the new Future with the Future you return to closure or with error if the first Future contains error.

let future = Future<Int>(value: 1)

let flatMapFuture = future.flatMap { value -> Future<String> in
    return Future<String>(value: "\(value * 100)%")
}
flatMapFuture.onSuccess { value in
    print(value) // "100%"
}

filter

Returns the Future if value satisfies the filtering else returns error.

let future = Future<Int>(value: 500)

future.filter { value -> Bool in
    return value > 100
}.onComplete { result in
    switch result {
    case .value(let value):
        print(value) // 100
    case .error(let error):
        print(error) // no error
    }
}

future.filter { value -> Bool in
    return value > 1000
}.onComplete { result in
    switch result {
    case .value(let value):
        print(value) // no value
    case .error(let error):
        print(error) // FutureError.filterError
    }
}

recover

If the Future contains or will contain error you can recover it with the new value.

let future = Future<Int>(error: someError)

future.recover { error -> Int in
    return 100
}.onComplete { result in
    switch result {
    case .value(let value):
        print(value) // 100
    case .error(let error):
        print(error) // no error
    }
}

zip

Combines two values into a tuple.

let first = Future<Int>(value: 1)
let second = Future<Int>(value: 2)

first.zip(second).onSuccess { firstValue, secondValue in
    print(firstValue) // 1
    print(secondValue) // 2
}

andThen

Returns the new Future with the same value.

let future = Future<String>(value: "and")

future.andThen { value in
    print(value) // "and"
}.andThen { value in
    print(value.count) // 3
}

flatten

If the value of the Future is the another Future you can flatten it.

let future = Future<Future<String>>(value: Future<String>(value: "value"))

future.onSuccess { value in
    print(value) // Future<String>(value: "value")
}

future.flatten().onSuccess { value in
    print(value) // "value"
}

Errors handling

map, flatMap, filter and recover can catch errors and return the Future with this error, so you don't need to handle it with do/catch.

let future = Future<String>(value: "")
let errorToThrow = NSError(domain: "", code: -1, userInfo: nil)

future.map { value -> String in
    throw errorToThrow
}.flatMap { value -> Future<String> in
    throw errorToThrow
}.filter { value -> Bool in
    throw errorToThrow
}.recover { error -> String in
    throw errorToThrow
}

Sequences

EasyFutures provides some functions to help you work with the sequences of Futures.

fold

You can convert a list of the values into a single value. Fold returns the Future with this value. Fold takes default value and then you perform action with default value and every value from the list. Can catch errors.

let futures = [Future<Int>(value: 1), Future<Int>(value: 2), Future<Int>(value: 3)]

futures.fold(0) { defaultValue, currentValue -> Int in
    return defaultValue + currentValue
}.onSuccess { value in
    print(value) // 6
}

traverse

Traverse can work with any sequence. Takes closure where you transform the value into the Future. Returns the Future which contains array of the values from the Futures returned by the closure.

[1, 2, 3].traverse { number -> Future<String> in
    return Future<String>(value: "\(number * 100)")
}.onSuccess { value in
    print(value) // ["100", "200", "300"]
}

sequence

Transforms a list of the Futures into the single Future with an array of values.

let futures = [Future<Int>(value: 1), Future<Int>(value: 2), Future<Int>(value: 3)] // [Future<Int>, Future<Int>, Future<Int>]
let sequence = futures.sequence() // Future<[Int]>
sequence.onSuccess { numbers in
    print(numbers) // [1, 2, 3]
}

License

EasyFutures is under MIT license. See the LICENSE file for more info.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].