A Promises Library for Swift 5.
This is a simple library that provides basic Promise functionality.
- Threadsafe
- Lightweight
- Cancellable
- The promises themselves don't manage all the threading functionality.
- It is the responsibility of the owner who makes the Promise to decide the Queues in which to create and fulfill the Promise.
- The receiver of the Promise can always change the Queue in which to receive the result of the Promise.
- Promises can only be fulfilled once.
- Swift Package Manager
Typically the Promiser creates a Promise in a determined Queue and returns it immediately to the Receiver:
func requestUser() -> Promise<User> {
let promise = Promise<User>()
networkingQueue.async {
// make HTTP request to get the user
}
return promise
}
Some time in the future the Promiser fulfills the promise on a determined Queue and the Receiver uses the result.
do {
let result = try JSONDecoder().decode(User.self, from: data)
promise.fulfill(with: result, in: responseQueue)
} catch {
promise.complete(with: error, in: responseQueue)
}
The Receiver of the Promise adds the necessary closures to it, there are four kinds of
closures that can be added the the Promise: then
onSuccess
onError
and finally
:
requestUser()
.then(requestFavorites(of:))
.onSuccess(updateFavorites)
.onError(logError)
.finally(updateView)
More than one closure can be added to every Promise.
It is possible to chain promises using then
, this method accepts a closure or function that
will be called with the result of the previous promise once completed and will return a new
promise:
requestInt(from: "1")
.then(requestString(from:))
.then(requestInt(from:))
.then(requestString(from:))
.onSuccess { result in
print(result)
}
The Queue in which the then
, onSuccess
, onError
or finally
closures are called is
determined by the following rules:
- If the closure is registered with a specific queue, then the closure will be called in that queue:
requestInt(from: "1").onSuccess(in: .main) { result in
print("in main queue: \(result)")
}
If a queue is not specified:
requestInt(from: "1").onSuccess { result in
print("\(result)")
}
then:
- If the Promiser specifies a closure when fulfilling the promise, then the closure will be called in that queue:
promise.fulfill(with: result, in: .global())
If a queue is not specified:
promise.fulfill(with: result)
then:
- The closure is called in the current queue in which the
fulfill
method is called.
A promise can be cancelled by the Receiver by calling it's cancel
method, in which case
the onError
closures will be called with the PromiseFailure.cancelled
error:
let promise = requestUser().onError(logError)
promise.cancel()