I've spent the better part of the day banging my head against the wall over this, and I think I finally understand it. Here's the question I wish had existed this morning when I started looking.
For background, I have several years of experience working with C++ and Python, and I've recently started learning Swift for non-iOS development. Everything I will show here seems to behave the same on a MacBook Pro as on my Ubuntu PC. I'm running Swift 5.4, compiling and running with Swift Package Manager in the command line.
I've read through several articles about using Promises in Swift, and it's not adding up. The examples they show make it seem like you can just call firstly
, chain together a few .then
calls, and then tie it all up with a .done
and a .catch
, and everything will just work. When I try this, I mostly get a bunch of errors, but sometimes I get lucky enough to have it compile, only to find that nothing is happening when I run it.
Here's an example main.swift
file that illustrates my confusion.
import PromiseKit
firstly {
Promise<String> { seal in
print("Executing closure")
seal.fulfill("Hello World!")
}
}.done { str in
print(str)
}
When I run this, it just prints Executing closure
, even if I add a sleep after it, or if I call .wait()
on the result. Why does the firstly
block execute but not the done
block?
Here's another one. It took me a while just to get it to compile, but it still doesn't do what I expect it to:
import Foundation
import PromiseKit
let url = URL(string: "https://stackoverflow.com/")!
enum SampleError: Error {
case noResponse
case badCode(Int)
case couldNotDecode
}
firstly {
Promise<Data> { seal in
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
return seal.reject(error)
}
guard let data = data, let response = response as? HTTPURLResponse else {
return seal.reject(SampleError.noResponse)
}
guard (200..<300).contains(response.statusCode) else {
return seal.reject(SampleError.badCode(response.statusCode))
}
seal.fulfill(data)
}.resume()
}
}.then { data -> Promise<String> in
Promise<String> { seal in
if let str = String(data: data, encoding: .utf8) {
seal.fulfill(str)
} else {
seal.reject(SampleError.couldNotDecode)
}
}
}.done { str in
print(str)
}.catch { error in
print("Error: \(error)")
}
I want this to print the HTML contents of the Stack Overflow home page, but instead it prints nothing.
It seems that I have all the setup in place, but the Promises are not running. How to I get them to actually execute?