Reputation: 36139
I'm trying to tame some callback hell pyramid of doom code using PromiseKit.
To do this I wrap my asynchronous code in promises, but depending on how I return dependent promises, I encounter problems. If I unwrap the promise and fulfill/reject then all is well, though more verbose than I'd like. If I return a new dependent promise, then I get an early allocation and the promises are silently broken.
I realise this might not be idiomatic PromiseKit, which appears to be
{ a }.then { b }.then { c } // in temporal order, take that, callbacks!
but as part of this work it's convenient for me to refactor with functions Promise<A> -> Promise<B>
, and I don't understand why I must unwrap at every step. Does anyone know?
Here is some simplified code that reproduces the problem. Try to imagine that there's a good reason that badStringFromInt
can't fulfil immediately.
func badStringFromInt(_ intPromise: Promise<Int>) -> Promise<String> {
return Promise { _, reject in
intPromise.then { i -> Promise<String> in
return Promise { fulfill, _ in
fulfill("\(i)")
}
}.catch { error in
reject(error)
}
}
}
func goodStringFromInt(_ intPromise: Promise<Int>) -> Promise<String> {
return Promise { fulfill, reject in
intPromise.then { i in
fulfill("\(i)")
}.catch { error in
reject(error)
}
}
}
func getInt() -> Promise<Int> {
return Promise{ fulfill, reject in
fulfill(5)
}
}
func doIt() {
// "then" never called, and this is logged:
// PromiseKit: Pending Promise deallocated! This is usually a bug
badStringFromInt(getInt()).then { s in
print("bad string is :" + s)
}.catch { error in
print("error: \(error)")
}
// all good!
goodStringFromInt(getInt()).then { s in
print("good string is :" + s)
}.catch { error in
print("error: \(error)")
}
}
Upvotes: 0
Views: 1356
Reputation: 42598
I must be missing something. Why not just add on to the chain? What does creating the intermediate promise do for you?
betterStringFromInt
waits for intPromise
to fulfill, then returns a string promise.
func betterStringFromInt(_ intPromise: Promise<Int>) -> Promise<String> {
return intPromise.then { i in
DispatchQueue.main.promise {
return "\(i)"
}
}
}
Upvotes: 1