0

I'm using NGRX and RxJS in Angular2 application. When use try to save record update, I generate an action 'UPDATE', and I want to call API to update Database.

The issue is that everything after ".filter ( action => action.type==UPDATE )" is invoke 4 times.

I don't understand why. I try manything and code change but issue still here...

My code :

private actions$ : BehaviorSubject<Action> = new BehaviorSubject<Action>({type: null, payload: null});

.../.... 

// catch employee selection
let update = this.actions$                                  
            .filter ( action => action.type==UPDATE )
             // **** following are executed 4 times ****
            .do( () => this._store.dispatch({type: REDUCER_UPDATING }) )
            .mergeMap ( action =>this._APIService.updateEmployee(action.payload) );  //  


// merge all stream and dispatch action
let all = Observable.merge (update, load, selectItem);
all.subscribe ((action:Action) => this._store.dispatch (action));

To see issue live :

https://plnkr.co/edit/zq4AsKJYILfrgItDNbHo?p=preview

Select an employee in Master Panel. In details panel, click save button. You will see in console that API is called 4 times :

REDUCER - {"type":"SELECTING_ITEM","payload":1}
REDUCER - {"type":"UPDATING"}
API - UPDATE_EMPLOYEE          <====1
REDUCER - {"type":"UPDATING"}
API - UPDATE_EMPLOYEE          <====2
REDUCER - {"type":"UPDATING"}
API - UPDATE_EMPLOYEE          <====3
REDUCER - {"type":"UPDATING"}
API - UPDATE_EMPLOYEE          <====4
REDUCER - {"type":"UPDATED"}

Thank you for your help !!

user3743222
  • 18,345
  • 5
  • 69
  • 75
Philippe sillon
  • 1,572
  • 2
  • 14
  • 20
  • Small correction in code sample. I don't use do operator but mergeMap : `// catch employee selection let update = this.actions$ .filter ( action => action.type==UPDATE ) .do( () => this._store.dispatch({type: REDUCER_UPDATING }) ) .mergeMap ( action =>this._APIService.updateEmployee(action.payload) ); ` – Philippe sillon Feb 16 '16 at 17:07

1 Answers1

2

I replaced the update part with :

// catch employee selection
let update = this.actions$                                  
            .filter ( action => action.type==UPDATE )
             // **** following are executed 4 times ****
            .do( () => this._store.dispatch({type: REDUCER_UPDATING }) )
            .mergeMap ( action =>this._APIService.updateEmployee(action.payload) )
            .share();  //  

This results in only one update appearing in the log.

The reason you observe the duplication of the updates is because every time you subscribe to the update stream, the observable chain is 'restarted'. This is what is called in RxJS a cold observable. The solution is simple, just add share at the end of the observable that you want to share between several subscribers.

For more details on hot vs. cold, see the official documentation. You can also review the illustrated data and subscription flows.

Community
  • 1
  • 1
user3743222
  • 18,345
  • 5
  • 69
  • 75
  • I don't see any change in your code example ;) . I try to add .share () to update expression and this fix issue. I will read your reference to understand when this is require ! thank you for your help ! Really ! – Philippe sillon Feb 16 '16 at 18:18
  • oh yeah, I pasted the code from the wrong plunkr. Sorry for that. Updated the code now. About the multiple subscriptions, one of them you gave here `all.subscribe ((action:Action) => this._store.dispatch (action));` There are several other places where you have things (from memory, I can't look at the code right now) like `all.map` put into other streams which are subscribed later on. So the `all` is subscribed several times, resulting in the update subscribed several times. If you don't see the related subscriptions, then it means it is Angular2 who operates the subscription behind the scene. – user3743222 Feb 16 '16 at 19:35
  • Ok, yes you right. I see now where I have multiple subscriptions ! Thank you for your response : I lost many times to figured-out what was wrong but now, I can progress ! :) Tx again ! – Philippe sillon Feb 16 '16 at 19:58