-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
the closure for ensure() should return a Promise to make the containing chain composable #838
Comments
Yes I've needed something like this before, seems like this would be enough: func ensure(on: DispatchQueue? = conf.Q.return, _ body: () -> Promise<Void>) -> Promise {
let promise = Promise<T>(.pending)
pipe { result in
on.async {
body().pipe {
promise.box.seal(result)
}
}
}
return promise
} I think this would not cause ambiguity, so we can call it |
I am not sure if this implementation as it is now propagates the errors. If body() rejects, the error will not be returned to the caller of ensure. We need to combine the two results. But using the internal APIs is definitely faster. |
True. Which makes me think that we can only have a Because if the promise you return rejects which error and the promise we are part of is already rejected which ```swift
func ensure(on: DispatchQueue? = conf.Q.return, _ body: () -> Guarantee<Void>) -> Promise {
let promise = Promise<T>(.pending)
pipe { result in
on.async {
body().done {
promise.box.seal(result)
}
}
}
return promise
} |
It seems reasonable that any async thing you do in |
I think that typically it wouldn't, and most closures could return a Guarantee. But in some rare cases there could be code that might error, and in those cases, it would be nice to get that error instead of ignoring it. The chain may completely roll back something but still recover rather than being left in an inconsistent state. |
In terms of which error to propagate: ideally, there could be an inner / nested error; but short of that, I think it should be the first error, the one before calling the closure. The other one is secondary; if it can't be returned as a nested error, logging it could be the next best thing. It's definitely an edge case, but this would give the user more tools to deal with errors. |
We once nested errors for So I think it better we don’t do that. Do you have examples where you have to return a |
The nested error would be more for debugging than handling the error, but logging it and returning the original error would also work. Examples: Any cleanup action that may be asynchronous. Animation is the first generic example that comes to mind. More specifically: animated dismissal of a view controller / hiding the UI that stared the chain. Another example could be showing additional UI at the end fo the chain (no matter successful or not) before completing the chain. |
Both these examples would be In the past I had a ticket with some networking cleanup though. That ofc. could error, but certainly it's a rarer situation IME. |
I thought more about this. The semantics does become crystal clear if it's a Guarantee while making it a Promise introduces ambiguity, so maybe a Guarantee is a better choice. I also cannot think of any real use cases for Promise and was more thinking about making it as generic as possible. |
K cool. I've prepared a PR. |
Great, thank you! |
Merged, will release when I have stable master. |
PromiseKit 6 (but applies to 4 as well)
Even though the
ensure
operator returns a promise, it assumes that its closure is synchronous; calls it and then immediately returns the promise that it's being applied to. The assumption is that ensure is expected to run at the end of the chain, so it doesn't need to be asynchronous. This works ifensure
is used only in that way but breaks if we want to turn the chain into a reusable (compound) promise.I wrote more about it here. It's possible to implement an overload of
ensure
this way usingrecover
. I think that it would be nice to have this overload as part of PromiseKit.The text was updated successfully, but these errors were encountered: