Google Promises

Google Promises is a rather recent player among Swift frameworks for async programming using futures and promises. You can add it as a dependency to your project using Swift Package Manager, CocoaPods, or Carthage. If you use Swift Package Manager, you can add the Promises dependency by including it in your Package.swift file, as in the following example:

let package = Package(
// ...
dependencies: [
.package(url: "https://github.com/google/promises.git", from: "1.2.3"),
],
// ...
)

If you use CocoaPods, just add the following to your Podfile:

pod 'PromisesSwift', '~> 1.2.3'

Then, refresh your dependencies by running the following:

pod install

Similarly, for Carthage, add the following to your Cartfile:

github "google/promises"

Then, run this command:

carthage update
If you work at Google, you might find it useful to know that Google Promises supports Bazel, as well—the build tool in use at Google.

Once you have added the Promises framework dependency to your project, you can import the Promises module into your Swift source files as follows:

import Promises

Let's reimplement the same example as used earlier using Google Promises. Contrary to PromiseKit, since the Google Promises framework does not provide a promise-based async wrapper for Swift Foundation APIs, the first bit of code we'll need is such a wrapper for URLSession.dataTask. Let's call it promisedData

func promisedData(_ url: URL) -> Promise<Data> {
let urlRequest = URLRequest(url: url)
let defaultSession = URLSession(configuration: .default)
return wrap { (handler: @escaping (Data, Error?) -> Void) in
let task = defaultSession.dataTask(with: urlRequest) { (data, response, error) in
if let data = data {
handler(data, error)
} else {
handler(Data(), error)
}
}
task.resume()
}
}

As you can see, all the heavy lifting is done by the Promises' wrap function, and we just have to provide a proper callback adapter. Once that function is available, we can set out to use GitHub REST API to retrieve the most starred repository first, followed by the most forked one:

func testGitHubAPI () {
if var urlComponents = URLComponents(string: "https://api.github.com/search/repositories") {

urlComponents.query = "q=sort=stars;order=desc;per_page=1"

let p : Promise<Data> = promisedData(urlComponents.url!)
p.then { data -> Promise<Data> in
let string = String(data:data, encoding:String.Encoding.utf8)
print("Most starred repo: \(string!)")
urlComponents.query = "q=forks=stars;order=desc;per_page=1"
return promisedData(urlComponents.url!)
}.then { data -> Promise<Data> in
let string = String(data:data, encoding:String.Encoding.utf8)
print("Most forked repo: \(string!)")
return Promise(data)
}.catch { error in
print("This was unexpected: \(error)")
}
}
}

Besides supporting the basic chaining then and catch functions, Google Promises provides a number of other functions that aim to make it easy to write complex asynchronous workflows, including the following:

As mentioned, there exist several open source frameworks for promise-based asynchronous operation handling. What you learned in this section will allow you to pick up any of them and get up to speed quickly.