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()