Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore a certain Error and terminate Promise #201

Open
kientux opened this issue Jan 3, 2023 · 5 comments
Open

Ignore a certain Error and terminate Promise #201

kientux opened this issue Jan 3, 2023 · 5 comments

Comments

@kientux
Copy link

kientux commented Jan 3, 2023

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 catches 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.

@jeff-h
Copy link
Contributor

jeff-h commented Jan 3, 2023

I was about to say, use recover — can you explain why it's not working for your use-case? Another option might be always?

@chuckhays
Copy link
Collaborator

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?

@kientux
Copy link
Author

kientux commented Jan 4, 2023

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 catches 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 😁

@kientux
Copy link
Author

kientux commented Jan 4, 2023

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.

@kientux
Copy link
Author

kientux commented Jan 4, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants