I have failed to find any usefull information about this library or what is the purpose of it. It seems like ngrx/effects explain this library to developers who already know this concept and gives a bigginer example on how to code.
My questions:
- What are sources of actions?
- What is the purpose of ngrx/effects library;what is the downside of only using ngrx/store?
- When it is recommended to be used?
- Does it support angular rc 5+? How do we configure it in rc 5+?
Thanks!
The topic is too wide. It will be like a tutorial. I will give it a try anyway. In a normal case, you will have an action, reducer and a store. Actions are dispatched by the store, which is subscribed to by the reducer. Then the reducer acts on the action, and forms a new state. In examples, all states are at the frontend, but in a real app, it needs to call backend DB or MQ, etc, these calls have side effects. The framework used to factor out these effects into a common place.
Let's say you save a Person Record to your database,
action: Action = {type: SAVE_PERSON, payload: person}
. Normally your component won't directly callthis.store.dispatch( {type: SAVE_PERSON, payload: person} )
to have the reducer call the HTTP service, instead it will callthis.personService.save(person).subscribe( res => this.store.dispatch({type: SAVE_PERSON_OK, payload: res.json}) )
. The component logic will get more complicated when adding real life error handling. To avoid this, it will be nice to just callthis.store.dispatch( {type: SAVE_PERSON, payload: person} )
from your component.That is what the effects library is for. It acts like a JEE servlet filter in front of reducer. It matches the ACTION type (filter can match urls in java world) and then acts on it, and finally returns a different action, or no action, or multiple actions. Then the reducer responds to the output actions of effects.
To continue the previous example, with the effects library:
The weave logic is centralised into all Effects and Reducers classes. It can easily grow more complicated, and at the same time this design makes other parts much simpler and more re-usable.
For example if the UI has auto saving plus manually saving, to avoid unnecessary saves, UI auto save part can just be triggered by timer and manual part can be triggered by user click. Both would dispatch a SAVE_CLIENT action. The effects interceptor can be:
The call
only works once if there is an error. The stream is dead after an error is thrown because the catch tries on outer stream. The call should be
Or another way: change all ServiceClass services methods to return ServiceResponse which contains error code, error message and wrapped response object from server side, i.e.
One correction to my previous comment: Effect-Class and Reducer-Class, if you have both Effect-class and Reducer-class react to the same action type, Reducer-class will react first, and then Effect-class. Here is an example: One component has a button, once clicked, called:
this.store.dispatch(this.clientActions.effectChain(1));
which will be handled byeffectChainReducer
, and thenClientEffects.chainEffects$
, which increases the payload from 1 to 2; wait for 500 ms to emit another action:this.clientActions.effectChain(2)
, after handled byeffectChainReducer
with payload=2 and thenClientEffects.chainEffects$
, which increases to 3 from 2, emitthis.clientActions.effectChain(3)
, ..., until it is greater than 10,ClientEffects.chainEffects$
emitsthis.clientActions.endEffectChain()
, which changes the store state to 1000 viaeffectChainReducer
, finally stops here.If you run the above code, the output should look like:
It indicates reducer runs first before effects, Effect-Class is a post-interceptor, not pre-interceptor. See flow diagram: