Reputation: 127
For example, I dispatch an action. This action dispatches some other action and this is a kind of chain of actions. Depends on the input the chain of actions may be different. When I dispatch an action I do not know the last action so I can not subscribe to concrete action on its success. So my question is how can I get information that all actions are done?
actions:
export class ActionOne {
static readonly type = 'Action one';
constructor(public payload: boolean) { }
}
export class ActionTwo {
static readonly type = 'Action two';
constructor(public payload: boolean) { }
}
export class ActionThree{
static readonly type = 'Action three';
constructor(public payload: boolean) { }
}
state:
@Action(ActionOne)
actionOne(ctx: StateContext<StateModel>, action: ActionOne): void {
ctx.dispatch(new ActionTwo());
}
@Action(ActionTwo)
actionTwo(ctx: StateContext<StateModel>, action: ActionTwo): void {
if(payload) ctx.dispatch(new ActionThree()); else ctx.setState....
}
@Action(ActionThree)
actionThree(ctx: StateContext<StateModel>, action: ActionThree): void {
ctx.setState....
}
action one dispatch
this.store.dispatch(new ActionOne(true)) // I don't know a path and last action, but I want to know when it is finished
this.store.dispatch(new ActionOne(false)) // I don't know a path and last action, but I want to know when it is finished
actions can be async!
Upvotes: 0
Views: 613
Reputation: 340
I think you can accomplish this by using the action
stream to track when your chain has been completed.
First off we need to be sure that the actions life cycle is bound and for this, we need to adjust a bit the code from your second snippet to:
@Action(ActionOne)
actionOne(ctx: StateContext<StateModel>, action: ActionOne): void {
return ctx.dispatch(new ActionTwo()); // return dispatch here
}
@Action(ActionTwo)
actionTwo(ctx: StateContext<StateModel>, action: ActionTwo): void {
if(payload)
return ctx.dispatch(new ActionThree()); // return the dispatch here
else ctx.setState
}
@Action(ActionThree)
actionThree(ctx: StateContext<StateModel>, action: ActionThree): void {
ctx.setState....
}
Notice that by returning the dispatch observable in your action handler you'll be binding the action life cycle properly. Meaning that the ActionOne
will be only complete once the ActionTwo
is completed.
Now you can watch for the completion of your actions using the action
stream provided by NGXS. Like the snippet shown below:
import { Actions, ofActionCompleted } from '@ngxs/store'
@Injectable()
export class MyService {
constructor(private action$: Actions) {
this.action$.pipe(
ofActionCompleted(ActionOne) // filter the action you desire
tap((x) => /* DO SOMETHING ABOUT IT */)
)
}
}
For the value x
inside the tap you'll receive a object of type ActionCompletion<T>
where T
is the action type, in this case ActionOne
. This interface can be seem ion the snippet below:
interface ActionCompletion<T = any> {
action: T;
result: {
successful: boolean;
canceled: boolean;
error?: Error;
};
}
Upvotes: 1