write a promise class in swift

To write a Promise class in Swift, you can start by creating a generic class that represents a value that may not yet be available. Here is an example implementation:

main.swift
class Promise<T> {
  private var result: Result<T, Error>?
  private var callbacks = [(Result<T, Error>) -> Void]()
  
  func resolve(result: Result<T, Error>) {
    self.result = result
    for callback in callbacks {
      callback(result)
    }
  }
  
  func then<U>(onSuccess: @escaping (T) -> Promise<U>) -> Promise<U> {
    let promise = Promise<U>()
    callbacks.append { result in
      switch result {
      case let .success(value):
        onSuccess(value).then { promise.resolve(result: $0) }
      case let .failure(error):
        promise.resolve(result: .failure(error))
      }
    }
    if let result = result {
      resolve(result: result)
    }
    return promise
  }
}
691 chars
28 lines

This Promise class has a private result property that is set when the promise is resolved, and a list of callbacks that are called when the promise is resolved. The resolve() method updates the result property and calls all registered callbacks.

The then() method is a way to chain promises. It takes a closure that accepts the T value of this promise and returns another promise (Promise<U>). When this promise is resolved, the closure is executed, and the resulting promise is resolved with the same result. If the current promise fails, the resulting promise is also failed.

Example usage:

main.swift
func fetchTodo() -> Promise<String> {
  let promise = Promise<String>()
  DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
    promise.resolve(result: .success("Do the dishes"))
  }
  return promise
}

func log(todo: String) -> Promise<Void> {
  print("Todo: \(todo)")
  return Promise<Void>()
}

let todoList = fetchTodo()
  .then { log(todo: $0) }
  .then { _ in fetchTodo() }
  .then { log(todo: $0) }
414 chars
18 lines

In this example, fetchTodo() returns a promise that is resolved after one second. We chain two calls to then() that log the todo and call fetchTodo() again. The resulting promise (todoList) is the last promise in this chain.

gistlibby LogSnag