Future

public final class Future<Value> : AnyFuture
extension Future: Equatable

Container for a result that will be provided later.

Functions that promise to do work asynchronously return a Future<Value>. The receipient of a future can observe it to be notified, or to queue more asynchronous work, when the operation completes.

A Future<Value> is regarded as:

  • resolved, when a value is set
  • fulfilled, when a value is set and successful
  • rejected, when a value is not set, and an error occured

The provider of a Future<Value> creates a placeholder object before the actual result is available, immeadiately returning the object, providing a dynamic way of structuring complex dependencies for asynchronous work. This is common behavior in Future/Promise implementation across many languages. Referencing these resources may be useful if you’re unfamilliar with the concept of Promises/Futures:

The provider of a Future<Value> may be implemented as follows:

func performAsynchronousWork() -> Future<String> {
    let promise = Promise<String>()
    DispatchQueue.global().async {
        ... on success ...
        promise.fulfill("A string")
        ... on failure ...
        promise.reject(error)
    }
    return promise.future
}

When receiving a Future<Value>, you have a number of options. You can immediately observe the result of the future using whenResolved(), whenFulfilled(), or whenRjected(), or choose to do more asyncrhonous work before, or parallel to observing. Each Future<Value> can have multiple observers, which are used to both simply return a result, or to queue up other futures.

To perform more asynchronous work, once a Future<Value> is fulfilled, use flatMap(). To transform the fulfilled value of a future into another value, use flatMapThrowing().

Options for combining futures into a single future is provided using and(), fold(), and Future<Value>.reduce()

A Future<Value> differs from a Promise<Value> in that a future is the container of a result; the promise being the function that sets that result. This design decision was made, in this library as well as in many others, to prevent receivers of Future<Value> to resolve the future themselves.

  • Creates a pending future

    Declaration

    Swift

    public init()
  • Creates a resolved future

    Declaration

    Swift

    public init(resolved: Result<Value, Error>)

    Parameters

    resolved

    Result<Value, Error>

  • Creates a resolved, fulfilled future

    Declaration

    Swift

    public convenience init(fulfilledWith value: Value)

    Parameters

    value

    Value of the fulfilled future

  • Creates a resolved, fulfilled future

    Declaration

    Swift

    public convenience init(rejectedWith error: Error)

    Parameters

    error

    Error, rejecting the future

  • Indicates whether the future is pending

    Declaration

    Swift

    public var isPending: Bool { get }
  • Indicates whether the future is resolved

    Declaration

    Swift

    public var isResolved: Bool { get }
  • Indicates whether the future is fulfilled

    Declaration

    Swift

    public var isFulfilled: Bool { get }
  • Indicates whether the future is rejected

    Declaration

    Swift

    public var isRejected: Bool { get }
  • Indicates the result of the future. Returns nil if the future is not resolved yet.

    Declaration

    Swift

    public var result: Result<Value, Error>? { get }
  • Declaration

    Swift

    public static func == (lhs: Future, rhs: Future) -> Bool
  • When the current Future is fulfilled, run the provided callback returning a new Future<Value>.

    This allows you to dispatch new asynchronous operations as steps in a sequence of operations. Note that, based on the result, you can decide what asynchronous work to perform next.

    This function is best used when you have other APIs returning Future<Value>.

    Declaration

    Swift

    func flatMap<NewValue>(
        on queue: DispatchQueue = .futures,
        callback: @escaping (_ value: Value) -> Future<NewValue>) -> Future<NewValue>

    Parameters

    queue

    DispatchQueue on which to resolve and return a new future. Defaults to DispatchQueue.futures.

    callback

    A function that will receive the value of this Future and return a new Future<Value>.

    value

    The fulfilled value of this Future<Value>.

    Return Value

    A future that will receive the eventual value.

  • When the current Future is rejected, run the provided callback reurning a new Future<Value>.

    This allows you to proceed with some other operation if the current Future was rejected, due to an error you can recover from.

    If the calback cannot provide a Future recovering from the error, an error inside the callback should be thrown, or a Future which is rejected should be returned.

    Declaration

    Swift

    func flatMapIfRejected(
        on queue: DispatchQueue = .futures,
        callback: @escaping(Error) -> Future<Value>) -> Future<Value>

    Parameters

    queue

    DispatchQueue on which to resolve and return a new future. Defaults to DispatchQueue.futures.

    callback

    A function that will receive the error resulting in this Future<Value>s rejection.

    Return Value

    A future that will receive the eventual value.

  • When the current Future is fulfilled, run the provided callback returning a fulfilled value of the Future<NewValue> returned by this method.

    If the calback cannot provide a a new value, an error inside the callback should be thrown.

    Declaration

    Swift

    func flatMapThrowing<NewValue>(
        on queue: DispatchQueue = .futures,
        callback: @escaping (Value) throws -> NewValue) -> Future<NewValue>

    Parameters

    queue

    DispatchQueue on which to resolve and return a new value. Defaults to DispatchQueue.futures.

    callback

    A function that will receive the value of this Future and return a new Future<Value>. Throwing an error in this function will result in the rejection of the returned Future<Value>.

    Return Value

    A future that will receive the eventual value.

  • When the current Future is fulfilled, run the provided callback returning a fulfilled value of the Future<NewValue> returned by this method.

    Declaration

    Swift

    func map<NewValue>(
        on queue: DispatchQueue = .futures,
        callback: @escaping (Value) -> NewValue) -> Future<NewValue>

    Parameters

    queue

    DispatchQueue on which to resolve and return a new value. Defaults to DispatchQueue.futures.

    callback

    A function that will receive the value of this Future and return a new Future<Value>

    Return Value

    A future that will receive the eventual value.

  • When the current Future is fulfilled, run the provided callback returning a fulfilled value of the Future<NewValue> returned by this method.

    Declaration

    Swift

    func map<NewValue>(
        _ keyPath: KeyPath<Value, NewValue>,
        on queue: DispatchQueue = .futures) -> Future<NewValue>

    Parameters

    queue

    DispatchQueue on which to resolve and return a new value. Defaults to DispatchQueue.futures.

    keyPath

    A KeyPath<Value, NewValue> pointing to a value to return on the receiving Future<Value>.

    Return Value

    A future that will receive the eventual value.

  • When the current Future is rejected, run the provided callback returning a fulfilled value of the Future<NewValue> returned by this method.

    This allows you to provide a future with an eventual value if the current Future was rejected, due to an error you can recover from.

    Declaration

    Swift

    func recover(on queue: DispatchQueue = .futures, callback: @escaping (Error) -> Value) -> Future<Value>

    Parameters

    queue

    DispatchQueue on which to resolve and return a new value. Defaults to DispatchQueue.futures.

    callback

    A function that will receive the value of this Future<Value>, and return a new value of type NewValue.

    Return Value

    A future that will receive the eventual value.

  • Undocumented

    Declaration

    Swift

    func mapIfRejected(on queue: DispatchQueue = .futures, callback: @escaping (Error) -> Value) -> Future<Value>
  • Returns a new Future, that resolves when this and the provided future both are resolved. The returned future will provide the pair of values from this and the provided future.

    Note that the returned future will be rejected with the first error encountered.

    Declaration

    Swift

    func and<NewValue>(_ other: Future<NewValue>, on queue: DispatchQueue = .futures) -> Future<(Value, NewValue)>

    Parameters

    other

    A Future to combine with this future.

    queue

    Dispatch queue to observe on.

    Return Value

    A future that will receive the eventual value.

  • Returns a new Future<Value> that fires only when this Future<Value> and all provided Future<NewValue>s complete.

    A combining function must be provided, resulting in a new future for any pair of Future<NewValue> and Future<Value> eventually resulting in a single Future<Value>.

    The returned Future<Value> will be rejected as soon as either this, or a provided future is rejected. However, a failure will not occur until all preceding Futures have been resolved. As soon as a rejection is encountered, there subsequent futures will not be waited for, resulting in the fastest possible rejection for the provided futures.

    Declaration

    Swift

    func fold<NewValue, S: Sequence>(
        _ futures: S,
        on queue: DispatchQueue = .futures,
        with combiningFunction: @escaping (Value, NewValue) -> Future<Value>) -> Future<Value>
        where S.Element == Future<NewValue>

    Parameters

    futures

    A sequence of Future<NewValue> to wait for.

    queue

    Dispatch queue to observe on.

    combiningFunction

    A function that will be used to fold the values of two Futures and return a new value wrapped in an Future.

    Return Value

    A future that will receive the eventual value.

  • Returns a new Future<Value> that fires only when all the provided Future<NewValue>s have been resolved. The returned future carries the value of the initialResult provided, combined with the result of fulfilled Future<NewValue>s using the provided nextPartialResult function.

    The returned Future<Value> will be rejected as soon as either this, or a provided future is rejected. However, a failure will not occur until all preceding Futures have been resolved. As soon as a rejection is encountered, there subsequent futures will not be waited for, resulting in the fastest possible rejection for the provided futures.

    Declaration

    Swift

    static func reduce<NewValue, S: Sequence>(
        _ futures: S,
        on queue: DispatchQueue = .futures,
        initialResult: Value,
        nextPartialResult: @escaping (Value, NewValue) -> Value) -> Future<Value>
        where S.Element == Future<NewValue>

    Parameters

    futures

    A sequence of Future<NewValue> to wait for.

    queue

    Dispatch queue to observe on.

    initialResult

    An initial result to begin the reduction.

    nextPartialResult

    The bifunction used to produce partial results.

    Return Value

    A future that will receive the reduced value.

  • Returns a new Future<Value> that will resolve with result of this Future after the provided Future<Void> has been resolved.

    Note that the provided callback is called regardless of whether this future is fulfilled or rejected. The returned Future<Value> is fulfilled only if this and the provided future both are fullfilled.

    In short, the returned future will forward the result of this future, if the provided future is fulfilled.

    Declaration

    Swift

    func always(on queue: DispatchQueue = .futures, callback: @escaping () -> Future<Void>) -> Future<Value>

    Parameters

    queue

    Dispatch queue to observe on.

    initialResult

    An initial result to begin the reduction.

    callback

    A callback that returns a Future<Void> to be deferred.

    Return Value

    A future that will receive the eventual value.

  • Returns a new Future<Value> that will resolve with the result of this Future after the provided callback runs.

    Note that the provided callback is called regardless of whether this future is fulfilled or rejected.

    This method is useful for times you want to execute code at the end of a chain of operations, regarless of whether successful or not.

    Declaration

    Swift

    func alwaysThrowing(on queue: DispatchQueue = .futures, callback: @escaping () throws -> Void) -> Future<Value>

    Parameters

    queue

    Dispatch queue to observe on.

    callback

    Callback to run.

    Return Value

    A future that will receive the eventual value.

  • Returns a new Future, effectively discarding the result of the caller.

    This method is useful when the value of a future is of no consequence.

    Declaration

    Swift

    @discardableResult
    func discard(on queue: DispatchQueue = .futures) -> Future<Void>

    Parameters

    queue

    Dispatch queue to discard on.

    Return Value

    A future that will receive the eventual value.

  • Adds a FutureObserver<Value> to this Future<Value>, that is called when the future is fulfilled.

    An observer callback cannot return a value, meaning that this function cannot be chained from. If you are attempting to create a sequence of operations based on the result of another future, consider using flatMap(), flatMapThrowing(), or some of the other methods available.

    Declaration

    Swift

    @discardableResult
    func whenFulfilled(
        on queue: DispatchQueue = .futures,
        callback: @escaping (Value) -> Void) -> FutureObserver<Value>

    Parameters

    queue

    Dispatch queue to observe on.

    callback

    Callback invoked with the fulfilled result of this future

    Return Value

    A FutureObserver<Value>, which can be used to remove the observer from this future.

  • Adds a FutureObserver<Value> to this Future<Value>, that is called when the future is rejected.

    An observer callback cannot return a value, meaning that this function cannot be chained from. If you are attempting to create a sequence of operations based on the result of another future, consider using flatMap(), flatMapThrowing(), or some of the other methods available.

    Declaration

    Swift

    @discardableResult
    func whenRejected(
        on queue: DispatchQueue = .futures,
        callback: @escaping (Error) -> Void) -> FutureObserver<Value>

    Parameters

    queue

    Dispatch queue to observe on.

    callback

    Callback invoked with the rejection error of this future

    Return Value

    A FutureObserver<Value>, which can be used to remove the observer from this future.

  • Adds a FutureObserver<Value> to this Future<Value>, that is called when the future is resolved.

    An observer callback cannot return a value, meaning that this function cannot be chained from. If you are attempting to create a sequence of operations based on the result of another future, consider using flatMap(), flatMapThrowing(), or some of the other methods available.

    Declaration

    Swift

    @discardableResult
    func whenResolved(
        on queue: DispatchQueue = .futures,
        callback: @escaping (Result<Value, Error>) -> Void) -> FutureObserver<Value>

    Parameters

    queue

    Dispatch queue to observe on.

    callback

    Callback invoked with the resolved Result<Value, Error> of this future

    Return Value

    A FutureObserver<Value>, which can be used to remove the observer from this future.