Ignore a certain Error and terminate Promise
kientux opened this issue · 5 comments
Is there any way to completely ignore an Error? For example, when I reject a Promise with something like PromiseCancelledError
, I don't want the downstream catch
es to handle this error. I want the Promise to be terminated and produce no output at all. Both catch
and recover
are not working for this case.
I was about to say, use recover
— can you explain why it's not working for your use-case? Another option might be always
?
Breaking the chain like that seems to be against the goals of using promises and the code makes every attempt to not break the promise chain.
Is this a common pattern you need? Why can't the catch block handle it, or some catch along the way can catch it and substitute a more appropriate error?
A promise must always produce a value or an error. So catch
is not working like exception catch in Java. In Promise the error will go down to all catch
es even when you already handled it. If use recover
then it will eventually goes to then
.
Let say I store a Promise to trigger API request everytime users type to search box. So for every character, I should cancel the previous request. Because Promise does not offer a cancellation mechanism, so I reject the Promise with a PromiseCancelledError
.
func doSearch(query: String?) {
self.promise?.reject(PromiseCancelledError())
self.promise = doApiRequest(query: query)
}
If I use this only in one place then sure I can catch PromiseCancelledError
and just ignore it, or I can use recover
and produce a nil
value or something to indicate that then
shouldn't handle the value. But I want to put this in a base class and use it in several places, then the above approach will need a lot of boilerplate codes (and who uses that class must always be acknowledged about the cancelled error, which I think is not neccessary?)
I know that breaking the chain is not something Promise
is designed for, just want to know if it can support my usecase 😁
Best way I can think of is an extension like this:
extension Promise {
func catchIgnoreCancelled(_ handler: @escaping Catch) -> Promise<Value> {
self.catch({ error in
if error is PromiseCancelledError {
print("promise is cancelled")
} else {
handler(error)
}
})
}
}
but every catches must be replace with this.
Hmm, it seems that promise?.reject(...)
is not working.
let promise: Promise<String> = Promise { fulfill, reject in
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
fulfill("done")
}
}
.then({ s in
print(s)
})
.catch({ error in
print(error)
})
promise.reject(PromiseCancelledError())
print("Promise:", promise.description)
This code block still prints out "done"
instead of PromiseCancelledError
. Am I doing anything wrong here? The last line even prints out Promise: Rejected: PromiseCancelledError()
. Is fulfill
suppose to not be called after promise state is rejected?
Even this is not working:
let promise = Promise<String>
.pending()
.then({ s in
print("=========================== then:", s)
})
.catch({ error in
print("=========================== catch:", error)
})
promise.reject(CustomError())
Nothing is printed out. When I debug into sourcecode, _observers
is inserted for then
and catch
but when call reject
, _observers
is always nil.