-
Notifications
You must be signed in to change notification settings - Fork 403
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
🚀[FEATURE]: Cancel method on actions #940
Comments
I need this too. I have started a thread on slack, but I will write my use case and motivation here also. So, in NGRX world, it's common practice to store loading indicator and error object inside the state, and use MyActionSuccess and MyActionFailed pattern to control async action results. And it makes sense. If I have two parts of UI that visualize that part of the state, I want to show spinner in both components. The problem is lots of boilerplate with this. With NGXS actions$ handler, and ofActionSTATE operator, I think we have a great solution for reducing action boilerplate. But, there is one problem. We are not able to manually control action result ("DISPATCHED", "SUCCESSFUL", "CANCELED" or "ERRORED") manually, withing action handler. Imagine this scenario. I have modal which renders login-form component. Login form dispatches LoginAction, which is async action. If everything goes fine, modal is subscribed to ofActionSuccess(LoginAction) and closes modal. It's pretty much the same as the example with the alert in the documentation. I need to react on the action, not just on state change to close modal when login succeeds. The problem is with error scenario. My action handler has try catch block, and calls api with await. In catch block, i patch state with error. Since i handled an error, this action ends with "SUCCESSFUL" state, and get's picked up by ofActionSuccess operator, and closes modal. This is not desired outcome, because i would like to leave modal open, so that user can see that error message. Workarounds are:
So, the ability to manually fail or cancel action would be a great solution to this problem. It would allow actions to fail gracefully, and be handled both in terms of updating state with an appropriate message, and also react with alerts, snack bars, toasters or whatever when needed. |
This is a critical need. I need the ability as @thomas-ama has mentioned of having action guards. I think this should behave similar to route guards. The idea is that each action should be prevented from continuing successfully if certain rules are not met (such as not authenticated, incorrect role, etc.) |
@tdekoekkoek I believe implementing a guard system is overengineering, because the problem can really be solved easier for both developers using NGXS and those maintaining it. I personally like the proposed API, but it would mean that every action class must extend some other class (which provides However, while This way, we could have even greater control without breaking existing action definitions:
This way, we won't feel the need of adding |
This is by design. Action can be handled in 500 states and therefore it's not realistically possible to determine what value we have to return. Currently
No. Actions are commands in CQRS and there is no such concept as "returing result from command handler". |
Okay, but we still need a way to cancel the action from inside. Then someone will need to pass additional data as to why the action was canceled. In the end, we are still returning a value, one way or another, aren't we? |
Action handlers can return Observable/Promise because NGXS is able to process asynchronous job. That code that you showed is a little bit unusual as I'm not able to understand what
Actions are cancelable by providing |
@arturovt Sorry, I might have described it poorly. What I'm trying to achieve is to clear an input, but only if and after action succeeded. A simple, but concrete use case. In my example, I just used false and true values to represent canceled and successful action results respectively.
I've read a little bit about CQRS. Commands might not return a value, but events can still be emitted (action handlers in case of NGXS) and can even carry values. However,
Allowing it to carry results from action completion would make sense and doesn't contradict CQRS. Will that be a solution? |
@arturovt is actual? |
Just to bring up this old discussion again, I think that this could be solved in a slightly different way... Regarding the proposed solution: A potential alternative is this:
|
I'm submitting a...
Current behavior
From what I understand, an action can be cancelled only when the parameter
{ cancelUncompleted: true }
is present and an action arrives while a previous action is still being processed.Expected behavior
Add a
cancel()
method to cancel an action manually, as in the following example:What is the motivation / use case for changing the behavior?
I want to execute an action handler only when an action completes successfully (i.e. a new
nbPages
is set in the given example):Without this feature, the action dispatch must be included in a service method that decides if the action must be dispatched or not:
However, I have to inject this service wherever I want to dispatch my action. This creates dependencies on this service at several places in the code.
Moreover, if another dev was not aware of the
setNbPages()
method, he may directly dispatch an action and the conditionnbPages > 0
would never be checked. The idea is thus to centralise action guards in the state and cancel the action if the guards do not pass.The text was updated successfully, but these errors were encountered: