Utility Helpers

Then includes a variety of helper methods to handle common patterns and keep your code clean.

chain

The .chain() method allows you to perform a side-effect without modifying the value being passed down the promise chain. The block you provide receives the promise's result but its return value is ignored. The original result is passed to the next .then().

This is perfect for tasks like logging or analytics.

extension Photo {
    public func post() -> Promise<Photo> {
        return api.post(self).chain { _ in
            Tracker.trackEvent(.postPicture)
        }
    }
}

// Usage:
photo.post().then { postedPhoto in
    // postedPhoto is the original photo object, not the result of the tracking event.
}

noMatterWhat

The .noMatterWhat() method is like a finally that can be placed in the middle of a chain. It executes its block whether the preceding promise succeeded or failed, and then passes the original result (or error) through to the next link in the chain.

This is useful for managing state that needs to be cleaned up before the entire chain is complete.

func fetchNextPage() -> Promise<[Item]> {
    self.isLoading = true
    return api.fetch()
        .registerThen(parseResponse)
        .noMatterWhat { // This block is always called
            self.isLoading = false
        }
}

// Usage:
fetchNextPage().then { items in
    // isLoading is already false here
}.onError { error in
    // isLoading is also false here
}

unwrap

The unwrap() global function converts an Optional into a Promise.

  • If the optional has a value, it returns a promise that is fulfilled with that value.
  • If the optional is nil, it returns a promise that is rejected with a PromiseError.unwrappingFailed error.

This helps to cleanly handle optionals at the start of a promise chain.

func process(userId: String?) -> Promise<Void> {
   return unwrap(userId).then { id in
        // id is a non-optional String here
        return network.get("/user/\(id)")
    }
}

first and last

If you have a promise that resolves with an array (Promise<[T]>), you can use .first() or .last() to get a promise that resolves with only the first or last element (Promise<T>). If the array is empty, the promise will fail with an unwrappingFailed error.

fetchUsers()
    .first()
    .then { firstUser in
        // Do something with the first user
    }

convertErrorToNil

The .convertErrorToNil() method transforms a Promise<T> into a Promise<T?>. If the original promise fails, instead of propagating the error, the new promise will successfully resolve with a nil value. This is useful for non-critical operations where a failure can be treated as an empty result.

fetchOptionalFeatureData()
    .convertErrorToNil()
    .then { data in
        // data is of type `Data?`
        if let actualData = data {
            // The feature is available
        } else {
            // The feature is not available or failed to load
        }
    }