Table of Contents
- Overview
- Features
- Getting Started
- Basics
- Extensions
- Installation
- Author
- Contribution
- License
- Changelog
Overview
DeLorean is a lightweight framework which allows you to write better async code in Swift. We designed DeLorean to be simple to use and also very flexible. It’s partially based on JavaScript A+ specs. We have added some useful features like progressable
and cancellable
promises. This promises layer queues all async task on background to avoid block the main thread.
Features
- Super friendly API
- Enum-based DSL to handle Promise state
- Promises can be dispatched on any thread or custom queue
- All promises are
Cancellable
andprogressable
- The framework has 100% test coverage
- No external dependencies
- Minimal implementation
- Support for
iOS/macOS/tvOS/watchOS
- Support for CocoaPods/Carthage/Swift Package Manager
Getting Started
This is a tiny example to build and execute a promise with DeLorean
.
let foobar = Promise { future in
future(.fulfill("foobar"))
}
foobar.then { value in
print(value)
}
Basics
Creating promises
You can create and Promise with enum DSL for async
operations.
let foobar = Promise { future in
future(.progress("foo"))
future(.fulfill("foobar"))
}
foobar.progress {
print($0)
}.then { string in
print(string)
}
Also, you can create and Promise with block API for async
operations.
let foobar = Promise { progress, fulfill, reject, cancel in
progress("foo")
cancel()
}
foobar.progress {
print($0)
}.cancel {
// ¯\_(ツ)_/¯
}
Then
You can simple chaining multiple asynchronous tasks.
let foobar = Promise { future in
future(.fulfill("foobar"))
}
promise.then { value in
print(value)
}
Or you can transform data between chainable promises.
let foobar = Promise { future in
future(.fulfill("foobar"))
}.then({ value in
print(value)
}).then({ value in
return value.count
}).then({ value in
return value > 0
})
Catch
This function allows you to handle Promise’s errors. The operator itself implicitly returns another promise, that is rejected with the same error.
let foobar = Promise<Void> { future in
future(.reject(SimpleError()))
}.then({ value in
print(value)
}).catch({ error in
// Handle simple error here
})
Progress
If there is an asynchronous action that can succeed
more than once, or delivers a series of values over time instead of just one, but you don’t want to finish the promise you can use this function.
let foobar = Promise<Int> { future in
future(.progress(0))
future(.progress(1))
future(.progress(2))
future(.fulfill(3))
}.progress({ value in
// This block is called multiple times
print(value)
}).then({ value in
// This block is called once
print(value)
})
Cancel
This function will trigger a callback that the promise can use to cancel its work. Naturally, requesting cancellation of a promise that has already been resolved does nothing, even if the callbacks have not yet been invoked.
let foobar = Promise<Int> { future in
future(.progress(0))
future(.cancel)
future(.fulfill(3))
}.progress {
print($0)
}.cancel {
// Handle cancellable work
}.then { value in
// This block is never called
print(value)
}
Extensions
All
This function create a Promise that resolved when the list of passed Promises resolves (promises are resolved in parallel). Promise also reject as soon as a promise reject for any reason.
let promise1 = Promise(value: 1)
let promise2 = Promise(value: 2)
let promise3 = Promise(value: 3)
let promise4 = Promise(value: 4)
let promise = Promise<Int>
.all([promise1, promise2, promise3, promise4])
.then { values in
for number in values {
print(number)
}
}
Always
This function allows you to specify a block which will be always executed both for fulfill and reject of the Promise.
let foobar = Promise<Int> { _ in
throw SimpleError()
}.then {
print($0)
}.catch {
// Handle error
}.always {
// This block is always called
}
Race
This function race many asynchronous promises and return the value of the first to complete.
let promise1 = Promise(value: 1)
let promise2 = Promise(value: 2)
let promise3 = Promise(value: 3)
let promise4 = Promise(value: 4)
let promise = Promise<Int>
.race([promise1, promise2, promise3, promise4])
.then { fastValue in
print(fastValue)
}
Recover
Recover lets us catch an error and easily recover from it without breaking the rest of the promise chain.
let foobar = Promise<Int> { _ in
throw SimpleError()
}.recover { error in
return Promise(value: 0)
}.then {
print($0)
}.catch {
// Handle error
}
Retry
Retry operator allows you to execute source chained promise if it ends with a rejection. If reached the attempts the promise still rejected chained promise is also rejected along with the same source error.
let promise = Promise<Int>
.retry(attempt: 3) { () -> Promise<Int> in
guard threshold != 1 else { return Promise(value: 8) }
threshold -= 1
return Promise(error: SimpleError())
}
Timeout
Timeout allows us to wait for a promise for a time interval or reject it, if it doesn’t resolve within the given time. The interval is expresed in seconds.
let promise = Promise<Int> { future in
future(.fulfill(5))
}.timeout(0.5)
Validate
Validate is a function that takes a predicate, and rejects the promise chain if that predicate fails.
let promise = Promise(value: 2)
.validate { $0 == 3 }
.catch { error in
// This promise always fails
}
Zip
This function allows you to join different promises (2, 3 or 4) and return a tuple with the result of them. Promises are resolved in parallel.
let promise1 = Promise(value: 0)
let promise2 = Promise(value: "foobar")
let zipped = Promise<Void>.zip(promise1, promise2)
.then { value1, value2 in
print(value1) // This function prints `0`
print(value2) // This function prints `"foobar"`
}
You can check the DeLorean.playground
to experiment with more examples. If you need to see deeply information you can check our Documentation
Installation
CocoaPods
DeLorean is available through CocoaPods. To install it, simply add the following line to your Podfile:
platform :ios, '10.0'
use_frameworks!
swift_version = '4.0'
target 'MyApp' do
pod 'DeLorean'
end
Carthage
You can also install it via Carthage. To do so, add the following to your Cartfile:
github 'therapychat/DeLorean'
Swift Package Manager
You can use Swift Package Manager and specify dependency in Package.swift
by adding this:
.Package(url: "https://github.com/therapychat/DeLorean.git", majorVersion: 0)
Author
Sergio Fernández, fdz.sergio@gmail.com
Contribution
For the latest version, please check develop branch. Changes from this branch will be merged into the master branch at some point.
- If you want to contribute, submit a pull request against a development
develop
branch. - If you found a bug, open an issue.
- If you have a feature request, open an issue.
License
DeLorean is available under the Apache License 2.0
. See the LICENSE file for more info.
Changelog
See CHANGELOG file.