2

I want to fire an action before sending a request to the server. Here is my code:

public fetchUserPrjects(action$: Observable<IProjectAction>, store: Store<IAppState>) {
    return action$.pipe(
      ofType(ProjectActionType.FETCH_USER_PROJECTS),
      mergeMap((action) => {
        store.dispatch(this._commonAction.showLoading()); // <== call action before request
         return this._projectService.getProjectList(action.payload)
          .map((result) => {
               return {
              project: result
            };
          });
      }),
      flatMap(data => [
        this._projectAction.addUserProjects(data),
        this._commonAction.hideLoading()
      ])
    ).catch((error) => {
      return Observable.of(this._commonAction.showError(error));
    })
    .concat(Observable.of(this._commonAction.hideLoading()));
  }

I have tried many ways and ended up this way. However, this way sometimes works but sometimes doesn't. Sometimes it freezes whole the process. How can I fire an action before sending the request to the server?

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
Amir Movahedi
  • 1,802
  • 3
  • 29
  • 52

2 Answers2

2

You could remove the showLoading dispatch from your fetchUserProjects epic and then just create a second epic with:

return action$.pipe(
      ofType(ProjectActionType.FETCH_USER_PROJECTS),
      map(() => this._commonAction.showLoading())
    );

The order of the execution does not really matter because the request this._projectService.getProjectList is asynchronous and will therefore definitely resolve afterwards.

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
  • Thanks! However the problem is that I want to pass the `action` for the `this._projectService.getProjectList(action.payload)`. With that if I execute `map(() => this._commonAction.showLoading())` first, I can't pass the action from `ofType()` function to `getProjectList()`. – Amir Movahedi Mar 26 '18 at 10:28
  • 1
    I think there was a misunderstanding so I've edited my answer to make it more clear. Nothing keeps you from having multiple epics 'listening' to the same action type. – Kim Kern Mar 26 '18 at 21:01
0

How about this:

 return action$.pipe(
      ofType(ProjectActionType.FETCH_USER_PROJECTS),
      flatMap(action => Observable.concat(
        this._projectService.getProjectList(action.payload)
            .map(this._projectAction.addUserProjects({ project: result}))
            .startWith(this._commonAction.showLoading())
            .catch(error => this._commonAction.showError(error)),
        Observable.of(this._commonAction.hideLoading())
      )))