Skip to content

RyuGames/SwiftPromises

Repository files navigation

SwiftPromises

Light-weight Promise package for Swift

Build Status codecov Version License Platform

Overview

SwiftPromises is a light-weight package to implement Promises in native Swift. It does not have any sub-dependencies and is meant to add Promise support with the most minimal code.

A Promise is an object representing the eventual completion/failure of an asynchronous operation. While it is available natively in some languages, it is not currently supported out of the box in Swift.

Inspired by Pierre Felgines' article "Implementing Promises in Swift", Khanlou's Promise library and Google's Promises framework.

Installation

SwiftPromises is available through CocoaPods. To install it, simply add the following lines to your Podfile:

pod 'SwiftPromises'

And run pod install.

Example Usage

Creating a Promise

The following defines a Promise that will resolve with the value 15.

let promise = Promise<Int> (15)

...

let promise = Promise<Int> {
  return 15
}

...

let promise = Promise<Int> { resolve, _ in
  resolve(15)
}

Promises can also reject with an Error.

let error = NSError(domain: "Error", code: -500, userInfo: [:])

let promise = Promise<Int> (error)

...

let promise = Promise<Int> {
  return error
}

...

let promise = Promise<Int> { _, reject in
  reject(error)
}

Then

The Then function can be used to handle a resolved Promise:

let promise = Promise<Int> { resolve, _ in
  resolve(1)
}

promise.then { (num) in
  print(num) // Prints 1
}

Catch

The Catch function can be used to handle a thrown error in a Promise:

let promise = Promise<Bool> { _, reject in
  reject(NSError(domain: "Error", code: -500, userInfo: [:]))
}

promise.catch { err in
  let err = err as NSError
  let message = err.domain
  print(message) // Prints "Error"
}

Chaining

Promises can be chained together:

func work1(_ string: String) -> Promise<String> {
  return Promise { resolve, _ in
    resolve(string)
  }
}

func work2(_ string: String) -> Promise<Int> {
  return Promise { resolve, _ in
    resolve(Int(string) ?? 0)
  }
}

func work3(_ number: Int) -> Int {
  return number * number
}

work1("10").then { string in
  return work2(string)
}.then { number in
  return work3(number)
}.then { number in
  print(number) // Prints 100
}

All

The All function can be used to call an array of Promises in parallel. All returns a new Promise that returns an array with resolved values. If one of the Promises in the array throws an error, All will call its Catch function.

let promise = Promise<Int> { resolve, _ in
  resolve(15)
}

let promise2 = Promise<Int> { resolve, _ in
  resolve(4)
}

all([promise, promise2]).then { (numbers) in
  var total = 0
  for number in numbers {
      total += number
  }
  print(total) // Prints 19
}.catch { (err) in
  // Not called in this example
}

Await

The Await function can be used to synchronously call a Promise.

let promise = Promise<Int> { resolve, _ in
  DispatchQueue.global().asyncAfter(deadline: .now() + 1, execute: {
    resolve(1)
  })
}

guard let value = try? await(promise: promise) else { return }

print(value) // Prints 1 after one second has passed

Note that the Await function should only be called with global threads to prevent deadlocking.

Contributing

We welcome contributors to SwiftPromises. Before beginning, please take a look at our contributing guidelines.

Author

WyattMufson - cofounder of Ryu Games

License

SwiftPromises is available under the MIT license.