Lazy Execution
A key characteristic of Then
's promises is that they are lazy or "cold". This means that a promise does not start its asynchronous operation the moment it is created. Instead, it remains in a dormant state until a consumer is attached to it.
Execution is triggered by calling one of the consuming methods:
.then()
.onError()
.finally()
.progress()
.start()
This behavior is intentional and differs from some other promise implementations (like JavaScript's). It allows you to construct a complex chain of operations without immediately triggering network requests or other side effects.
registerThen()
and Friends
What if you want to build a promise chain but defer its execution until later? This is where the register
family of methods comes in.
registerThen()
registerOnError()
registerFinally()
These methods behave exactly like their non-register counterparts (then
, onError
, finally
) but with one crucial difference: they do not start the promise chain.
This is particularly useful for creating reusable promise chains.
Example
Imagine you have a function that fetches JSON and another that parses it. You can create a combined promise that encapsulates both steps, but it won't execute until you're ready.
// This function constructs a promise but doesn't start it.
func fetchAndParseUsers() -> Promise<[User]> {
let userPromise = fetchUsersJSON()
.registerThen(parseUsersJSON)
// At this point, no network request has been made.
return userPromise
}
// Later in your code, when you actually need the users:
let users = fetchAndParseUsers()
// Now, by calling .then(), we trigger the entire chain to start.
users.then { userModels in
// The network request and parsing have completed.
print("Fetched \(userModels.count) users.")
}
Explicitly Starting with .start()
If you need to trigger a promise without attaching a .then
or .onError
block (a "fire and forget" operation), you can explicitly call the .start()
method.
let analyticsPromise = sendAnalyticsEvent("app_launch")
// We don't care about the result, but we need to start it.
analyticsPromise.start()