0
votes

I'm working on ngrx effects, I met this code :

@Effect()
  loadProjects$ = this.dataPersistence.fetch(ProjectsActionTypes.LoadProjects, {
    run: (action: LoadProjects, state: ProjectsState) => {
      return this.projectsService.all().pipe(map((res: Project[]) => new ProjectsLoaded(res)))
    },
    onError: (action: LoadProjects, error) => {
      console.error('Error', error);
    }
  });

Here this effect is listening to LoadProjects action, when it is triggered, it executes an http call function (this.projectsService.all()) and it is mapped to trigger another action which is ProjectsLoaded.

NB: The example above works as expected

return this.projectsService.all().pipe(map((res: Project[]) => new ProjectsLoaded(res)))

What I did not understand is how it triggers ProjectsLoaded action without even listening to the http call result which is an observable, without subscribe() ?

As you know, for normal observable making this won't work

const obs = new Observable((sub) => {
  sub.next(10);
  sub.complete();
});

obs.pipe(map((v) => console.log(v))); // nothing happen because we did not subscribe to the observable 
obs.pipe(map((v) => v)).subscribe((v)=>console.log(v)); // it works
1

1 Answers

0
votes

That happens because the inner Observable you mentioned is chained with the main Observable of the effect, which is subscribed by NgRx internally to listen to the action once dispatched.

So you can imagine it like chaining two Observables to each other using mergeMap like the following (from your example)

const obs1 = new Observable((sub) => {
    sub.next(10);
    sub.complete();
});

const obs2 = new Observable((sub) => {
    sub.next(20);
    sub.complete();
});

obs1.pipe(
    map((v1) => console.log(v1)), // it works
    mergeMap(() => obs2.pipe(map((v2) => v2)))
).subscribe((v2) => console.log(v2)); // it works