Controlling Promise Flow

Then provides several methods to control the timing and conditions under which a promise chain executes.

validate

The .validate() method allows you to insert an assertion into your promise chain. You provide a block that receives the promise's result and returns a boolean.

  • If the block returns true, the chain continues with the original result.
  • If the block returns false, the chain rejects with a PromiseError.validationFailed.

This is useful for ensuring data meets certain criteria before proceeding.

fetchUserAge()
    .validate { age in age >= 18 } // Check if user is an adult
    .then { age in
      // This is only called if the user is 18 or older
      offerAdultBeverage()
    }
    .onError { error in
        if let promiseError = error as? PromiseError, promiseError == .validationFailed {
            print("User is not old enough.")
        }
    }

You can also provide a custom error for the validation to throw:

.validate(withError: MyError.userIsUnderage, { $0 >= 18 })

delay

The .delay() method pauses the promise chain for a specified duration (in seconds) before continuing. The delay only occurs if the promise is successful.

showSuccessIndicator()
    .delay(2.0) // Wait for 2 seconds
    .then {
        hideSuccessIndicator()
    }

This can be useful for ensuring UI elements are visible for a minimum amount of time.

timeout

The .timeout() method sets a maximum time limit for a promise to resolve. If the promise does not resolve within the specified duration, it will automatically reject with a PromiseError.timeout error.

This is a powerful way to prevent your application from hanging on a long-running or stalled operation.

fetchResource()
    .timeout(5.0) // Fail if it takes longer than 5 seconds
    .then { resource in
        // We got the resource in time
    }
    .onError { error in
        if let promiseError = error as? PromiseError, promiseError == .timeout {
            print("The operation timed out.")
        }
    }