Now I am migrating from PromiseKit to Concurrency. As I understood, I should replace Promise
and Guarantee
with Task
. However, I cannot find a replacement for Promise<T>.pending()
. Is there something similar in Concurrency?
For instance, I want to use Task
in the code below:
import CoreLocation
import PromiseKit
class A: NSObject {
let locationManager = CLLocationManager()
let promiseAndResolver = Promise<CLLocation>.pending()
func f() {
locationManager.delegate = self
locationManager.requestLocation()
}
}
extension A: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
promiseAndResolver.resolver.fulfill(location)
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
promiseAndResolver.resolver.reject(error)
}
}
class B {
let a = A()
func f() {
a.promiseAndResolver.promise.done {
print($0)
}.cauterize()
a.f()
}
}
let b = B()
b.f()
You don't need to use Task
to do this. You can use withCheckedThrowingContinuation
to convert the method f
into an async throws
method. Then when you call it, a child task of the current task is automatically created and you can await
it directly.
class A: NSObject, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var continuation: CheckedContinuation<CLLocation, Error>?
func f() async throws -> CLLocation {
try await withCheckedThrowingContinuation { continuation in
self.continuation = continuation
locationManager.delegate = self
locationManager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
continuation?.resume(returning: locations[0])
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
continuation?.resume(throwing: error)
}
}
Your B.f
method can also be rewritten as an async
method (I don't know what cauterize
does):
class B {
let a = A()
func f() async {
do {
print(try await a.f())
} catch {
print(error)
}
}
}
let b = B()
_runAsyncMain { // so that we have an async context to await tasks
await b.f()
}
Side note: if you actually run this, you will get an error printed from the catch block, probably because location manager needs permission :)