-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Custom RxJS operator for safe calling the service in the Effect #1224
Comments
Ah, here is the stackblitz: https://stackblitz.com/edit/typescript-snyfkg |
I get the why, but I'm not really in favor of this.
But maybe I'm just a sucker for the RxJS operators 😅 |
@MikeRyanDev had a similar idea for a pipeable operator like this one. I think it has some value for repetitive mapping and error handling. |
Here's the proposal I submitted to redux-observable: redux-observable/redux-observable#457 They accepted it, I just haven't gotten around to implementing it in both locations. I welcome anyone to make the PR. |
This won't be enforced onto people, it's just safer and helpful alternative :)
That's true, but Honestly, in the internal code reviews every time I see
I love RxJS operators :) but every time I create an "interesting" combination/solution, I comment every line of it for my future self. @MikeRyanDev I can definitely create a PR for this.
|
@alex-okrushko Yea of course I'm not blocking. |
Some inner observables in effects notify multiple times and then complete.
Thinking of web socket connections and Http requests with status
notifications.
…On Thu, Aug 2, 2018 at 12:04 PM Tim Deschryver ***@***.***> wrote:
@alex-okrushko <https://github.com/alex-okrushko> Yea of course I'm not
blocking.
I honestly think this will start growing on me, especially after seing it
in action 😃
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1224 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ADilFXRvSIfRy1iMH3PmDJHDV_LnxfoVks5uMyMbgaJpZM4VrhwB>
.
|
is it possible to implement custom operator which would look at action's payload and if there is operator (switchMap, concatMap,..) present use it otherwise use some chosen default op.? |
Our app is heavily relying on effects for all the business logic. That's why a global error handler is critical because any exception stops the actions stream. Here is my solution. effects.service.ts
home.effects.ts
This will handle any unhandled exceptions and continue the actions stream. |
Regarding the requirement "I want unhandled errors not to completely break my action stream": I wonder why this is not part of the effects library itself? Wouldn't a appended |
@dummdidumm actually there is a |
Maybe (if they don't want it to be the default) there could be a new property to turn it on. @Effect({resubscribeAfterError: true})
streamThatWillContinueToWorkAfterError$ = ... |
No, it wouldn't work. It needs to be handled on the Observable before it's flattened into the main stream. |
I imagine something like this |
@alex-okrushko have you tried my solution? It works for me so it could work for others if implemented in effects lib. You only need to return the second argument of |
@jnorkus you're using a loose definition of "works" here.
Your idea is neat though. As a default selector I'd prefer returning EMPTY from it, so only the effect in err would unsubscribe from the action stream. |
Reviving this thread. BEFORE: const effect$: Observable<FooSuccess|FooError> = actions$.pipe(
ofType(FOO),
concatMap(a => this.service.fetch(a.bar).pipe(
map(resp => new FooSuccess(resp)),
catchError(e => of(new FooError()))
)),
); AFTER: const effect$: Observable<FooSuccess|FooError> = actions$.pipe(
ofType(FOO),
concatMap(a => this.service.fetch(a.bar).pipe(
mapToAction(
resp => new FooSuccess(resp),
e => new FooError(),
optionalComplete => new FooCompleted() // could be a good addition as Mike mentioned above?
))),
); It's not as 'in your face' as I'd like it to be (given how often I see this error), but at least promoting this new operator might bring some awareness. Alternatively, or in addition to it, we can have 4 operators that will wrap the flattening operators, const effecOp$: Observable<FooSuccess|FooError> = actions$.pipe(
ofType(FOO),
concatMapToAction( // <-- concatMap-based implementation
action => this.service.fetch(a.bar).pipe(map(resp => new FooSuccess(resp))),
error => new FooError()
),
); or even split the observable-provider function: const effecOp$: Observable<FooSuccess|FooError> = actions$.pipe(
ofType(FOO),
concatMapToAction( // <-- concatMap-based implementation
action => this.service.fetch(a.bar),
success => new FooSuccess(success),
error => new FooError()
),
); @timdeschryver @brandonroberts Thoughts? Also, ideally I'd like to get it into |
I'd like to keep the API surface small, keep the number of operators to update/add low, and not make users have to decide on which *MapToAction to use. I propose a separate option that combines the two ideas, with a default of const effecOp$: Observable<FooSuccess|FooError> = actions$.pipe(
ofType(FOO),
mapToAction( // <-- concatMap-based implementation
fromAction => this.service.fetch(a.bar).pipe(map(resp => new FooSuccess(resp))),
toError => new FooError(),
toOptionalComplete => new FooComplete()
),
); I think it would help streamline the sequence as a primary operator, and users have to worry less about nesting observable within a flattening operator. |
+1 to the |
I'm also proposing a new higher-order effect called |
I was thinking more about @jnorkus suggestion from #1224 (comment) and I think I like it now.
If anything, users would be able to remove that behavior with |
Many Effects are used to call services, and most of the time they should result in
SUCCESS
orERROR
actions.From the code that I review it's quite often that error case is either:
Even people who are familiar with all of these mistakes still make them sometimes.
Custom operator might help here, e.g.:
could turn into
where the
safeCall
(not crazy about the naming) would be that safety operator.the operator itself could be implemented like this:
Thoughts?
Should we add this to ngrx?
If accepted, I would be willing to submit a PR for this feature
[ x ] Yes (Assistance is provided if you need help submitting a pull request)
[ ] No
The text was updated successfully, but these errors were encountered: