Creating Promises

There are several ways to create a Promise in Then, from wrapping custom asynchronous operations to creating promises that are already resolved or rejected.

The Standard Initializer

The most common way to create a promise is by wrapping an asynchronous operation. The initializer provides resolve and reject closures for you to call when the operation completes.

import Then

enum NetworkError: Error {
    case invalidURL
}

func fetchData(from url: URL) -> Promise<Data> {
    return Promise { resolve, reject in
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let error = error {
                reject(error) // Operation failed
                return
            }
            if let data = data {
                resolve(data) // Operation succeeded
            } else {
                reject(NetworkError.invalidURL) // Custom failure case
            }
        }.resume()
    }
}

For operations that can report progress, a third progress closure is available. See Handling Progress for more details.

Promises with Void

For asynchronous operations that do not produce a value upon success (e.g., saving data), you can use Promise<Void> or the EmptyPromise typealias. The resolve closure takes no arguments.

func saveData(_ data: Data) -> Promise<Void> { // or EmptyPromise
    return Promise { resolve, reject in
        // Perform save operation...
        let success = true // a boolean indicating success
        if success {
            resolve(()) // or just resolve()
        } else {
            reject(SomeError.saveFailed)
        }
    }
}

Pre-resolved Promises

Sometimes you need to create a promise that is already in a completed state. This is useful for starting a promise chain with an existing value or for stubbing in tests.

Promise.resolve(value)

Creates a new promise that is already fulfilled with the given value.

let userPromise = Promise.resolve(User(name: "Alice"))

userPromise.then { user in
    print(user.name) // Prints "Alice" immediately
}

For Void promises, you can use Promise.resolve() with no arguments.

Promise.reject(error)

Creates a new promise that is already rejected with the given error.

let failedPromise = Promise<User>.reject(APIError.userNotFound)

failedPromise.onError { error in
    print(error) // Prints "userNotFound"
}

Convenience Initializers

Then also provides simple initializers for creating pre-resolved promises.

let p1 = Promise(123) // Same as Promise.resolve(123)
let p2 = Promise<Int>(error: MyError.defaultError) // Same as Promise.reject(MyError.defaultError)