Combining Promises
Then
provides several powerful utilities for working with multiple promises at once.
whenAll
Promises.whenAll
is used when you have multiple asynchronous operations and you need to wait for all of them to complete successfully before proceeding. It takes an array of promises (or a variadic list) and returns a new promise.
- This new promise fulfills with an array containing the results of all the input promises, in their original order.
- If any of the input promises reject, the
whenAll
promise immediately rejects with that same error.
let promiseA = fetchUsersA() // -> Promise<[User]>
let promiseB = fetchUsersB() // -> Promise<[User]>
let promiseC = fetchUsersC() // -> Promise<[User]>
Promises.whenAll(promiseA, promiseB, promiseC).then { allUsersArray in
// allUsersArray is a single array: [[User], [User], [User]]
// Let's flatten it
let allUsers = allUsersArray.flatMap { $0 }
print("Fetched a total of \(allUsers.count) users.")
}.onError { error in
print("One of the fetch operations failed: \(error)")
}
whenAll
also works with promises that return arrays themselves (Promise<[T]>
), and it will flatten the results into a single array [T]
.
race
Promises.race
takes multiple promises and returns a new promise that resolves or rejects as soon as the first of the input promises resolves or rejects. It's a race to the finish.
This is useful when you have multiple sources for the same data (e.g., a cache and a network request) and you want to use whichever one returns first.
let fetchFromCache = fetchResourceFromCache() // -> Promise<Data>
let fetchFromNetwork = fetchResourceFromNetwork() // -> Promise<Data>
Promises.race(fetchFromCache, fetchFromNetwork).then { data in
// This block is executed with the data from whichever promise finished first.
print("Got the resource!")
}
zip
Promises.zip
is used when you need to combine the results of multiple promises that have different types. It waits for all promises to complete successfully and then fulfills with a tuple containing all the results.
Like whenAll
, if any of the input promises fail, the zip
promise also fails.
let userPromise = fetchUser() // -> Promise<User>
let settingsPromise = fetchSettings() // -> Promise<Settings>
Promises.zip(userPromise, settingsPromise).then { (user, settings) in
// Both promises have completed successfully
print("Welcome, \(user.name). Your theme is \(settings.theme).")
}
Then
provides overloads for zip
to combine up to 8 promises.