Store: feat(ofAction): ofActionCompleted

Created on 14 Dec 2018  路  4Comments  路  Source: ngxs/store

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[X] Feature request
[ ] Documentation issue or request
[ ] Support request => https://github.com/ngxs/store/blob/master/CONTRIBUTING.md
[ ] Other... Please describe:

Current behavior


When I just want to know when an action has been ended (no matter if it's successful. errored or canceled), I need to merge all of them into one observable, and then continue.

Expected behavior


A method called ofActionComplete() which will emit after an action has been completed no matter if it was successful, errored or canceled.

What is the motivation / use case for changing the behavior?


Short example - I have a form with a loading indicator. onDispatch will set it to true. After the action has been completed, I would like to set the loading indicator back to false.

Environment


Libs:

  • @angular/core version: 3.3.0
  • @ngxs/store version: 3.3.0

For Tooling issues:

  • Node version: XX
  • Platform:

Most helpful comment

After reviewing your PR, I think that this requires a bit more thought...
This is what I am thinking:
There shouldn't be any new lifecycle events. We already have 'SUCESSFUL', 'CANCELED' and 'ERRORED' which all represent completion states.
The ofActionCompleted will return a different signature to the others. It will provide the action as well as the result that was encountered.
So the signature for the value returned by this filter could be as follows:

interface ActionCompleted<T> {
  action: T;
  result: {
    successful?: boolean;
    canceled?: boolean;
    error?: any;
  }
}

Note that an errored action would return the actual error object and not just a boolean.
This will make for a very powerful of-action operator. Especially since the user will be able to receive the actual error object, something that would provide a nice solution to issue #518 (the fact that ofActionErrored doe not return the error).
What do you think?
cc @splincode @eranshmil @deebloo

All 4 comments

I agree that this feature may be useful, but in your use case I prefer creating isLoading key in the state and using it with an async pipe.

@Newbie012 Yes! Thank you for raising this. It was supposed to be added in v3 but it never happened.

It should rather be called ofActionCompleted to match the tense of the other ofAction methods and also to avoid a conflict with the ofActionComplete from v2 that was renamed to ofActionSuccessful v3.

Would you like to have a go at doing a PR for adding ofActionCompleted?
You will need to also add some tests to packages\store\tests\action.spec.ts

After reviewing your PR, I think that this requires a bit more thought...
This is what I am thinking:
There shouldn't be any new lifecycle events. We already have 'SUCESSFUL', 'CANCELED' and 'ERRORED' which all represent completion states.
The ofActionCompleted will return a different signature to the others. It will provide the action as well as the result that was encountered.
So the signature for the value returned by this filter could be as follows:

interface ActionCompleted<T> {
  action: T;
  result: {
    successful?: boolean;
    canceled?: boolean;
    error?: any;
  }
}

Note that an errored action would return the actual error object and not just a boolean.
This will make for a very powerful of-action operator. Especially since the user will be able to receive the actual error object, something that would provide a nice solution to issue #518 (the fact that ofActionErrored doe not return the error).
What do you think?
cc @splincode @eranshmil @deebloo

@eranshmil According to the last 2 apps I built, I had to do multiple load indicators. Therefore, I moved these indicators to the component level (I made a small state-management system in my components).
I ended up doing something like:

this.store.dispatch(new CreateSubscription({
  plan: this.plan,
  card: {number, cvv, month, year, owner}
}))
  .pipe(
    finalize(() => this.patchState({loading: false})),
    takeUntil(this.ngUnsubscribe),
  )
  .subscribe({
    next: () => this.handleSuccessfulResponse(),
    error: err => this.handleHttpErrorResponse(err)
  });

@markwhitfeld As I mentioned in the PR, I agree with you. Although, I think that AuthStatus.Completed should be kept.

Was this page helpful?
0 / 5 - 0 ratings