Contents

Future

A publisher that eventually produces a single value and then finishes or fails.

Declaration

final class Future<Output, Failure> where Failure : Error

Mentioned in

Overview

Use a future to perform some work and then asynchronously publish a single element. You initialize the future with a closure that takes a Future.Promise; the closure calls the promise with a Result that indicates either success or failure. In the success case, the future’s downstream subscriber receives the element prior to the publishing stream finishing normally. If the result is an error, publishing terminates with that error.

The following example shows a method that uses a future to asynchronously publish a random number after a brief delay:

func generateAsyncRandomNumberFromFuture() -> Future <Int, Never> {
    return Future() { promise in
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            let number = Int.random(in: 1...10)
            promise(Result.success(number))
        }
    }
}

To receive the published value, you use any Combine subscriber, such as a Subscribers.Sink, like this:

cancellable = generateAsyncRandomNumberFromFuture()
    .sink { number in print("Got random number \(number).") }

Integrating with Swift Concurrency

To integrate with the async-await syntax in Swift 5.5, Future can provide its value to an awaiting caller. This is particularly useful because unlike other types that conform to Publisher and potentially publish many elements, a Future only publishes one element (or fails). By using the value property, the above call point looks like this:

let number = await generateAsyncRandomNumberFromFuture().value
print("Got random number \(number).")

Alternatives to Futures

The async-await syntax in Swift can also replace the use of a future entirely, for the case where you want to perform some operation after an asynchronous task completes.

You do this with the function withCheckedContinuation(isolation:function:_:) and its throwing equivalent, withCheckedThrowingContinuation(isolation:function:_:). The following example performs the same asynchronous random number generation as the Future example above, but as an async method:

func generateAsyncRandomNumberFromContinuation() async -> Int {
    return await withCheckedContinuation { continuation in
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            let number = Int.random(in: 1...10)
            continuation.resume(returning: number)
        }
    }
}

The call point for this method doesn’t use a closure like the future’s sink subscriber does; it simply awaits and assigns the result:

let asyncRandom = await generateAsyncRandomNumberFromContinuation()

For more information on continuations, see the Concurrency topic in the Swift standard library.

Topics

Creating a future

Accessing the value asynchronously

See Also

Convenience Publishers