Raj
Raj

Reputation: 1120

How to make multiple HTTP calls in Angular6, using forkJoin and ngrx?

Scenario

In my angular6 app, i have three cateories, catA, catB, catC. Each category needs data from 3 APIs. On clicking any category it loads the CategoryDetailsComponent, i dispatch action (LoadCategoryDetails).

I have implemented forjoin to perform parallel api calls(in service) and also resolver to ensure all the calls are done, only then the component should loaded.

Problem

Maybe one of the api call is taking time. and my resolver is not configured properly.

Question

How to configure effects and resolver??

How to use forkjoin to make multiple calls and send data to component?

Code

  1. dipatch action and subscribe to selector

    ngOnInit() {
        const id = parseInt(this.route.snapshot.paramMap.get('categoryId'), 10);
        this.store.dispatch(new fromCategory.LoadCategoryDetails(id));
    
        this.store.select(getCategoryDetails)
                  .subscribe((data) => {
                    this.categoryDetails = data[0];
                    this.journeys = data[1];
                    this.categories = data[2];
                  });
    
        // filter only category name
        // problem
        this.categories.forEach( category => {
          this.categoryNames.push(category.name);
        });
    }

  2. effects (look for action and call service)

    @Effect()
    loadCategoryDetails$ = this.actions$.pipe(
        ofType<fromCategory.LoadCategoryDetails>(CategoryActionTypes.LoadCategoryDetails),
        switchMap((action) => {
        return this.categoryService.getCategoryDetails(action.payload).pipe(
            map(data => new fromCategory.LoadCategoryDetailsSuccess(data))
        );
        })
    );

  3. service func making multiple calls and using forkjoin

    import { forkJoin } from 'rxjs';
    
    getCategoryDetails(categoryId) {
        const categoryDetails = this.http.get(url);
        const journeys = this.http.get(url);
        const courses = this.http.get(url);
    
        return forkJoin([categoryDetails, journeys, courses]);
    }

  4. resolver

    export class CategoryDetailsResolver implements Resolve<any> {
    
        constructor(
            private categoryService: CategoryService,
            private router: Router) {}
    
        resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
            const categoryId = route.paramMap.get('categoryId');
            return this.categoryService.getCategoryDetails(categoryId);
        }
    }

Thanks in advance.

Upvotes: 0

Views: 1135

Answers (2)

JBeckton
JBeckton

Reputation: 7111

refactor your code to NOT use route.snapshot and see if that fixes it.

ngOnInit() {
this.route.data.subscribe((data) => {

if(data) {
 this.store.dispatch(new fromCategory.LoadCategoryDetails(data.id));

 this.store.select(getCategoryDetails)
          .subscribe((data) => {
            this.categoryDetails = data[0];
            this.journeys = data[1];
            this.categories = data[2];

 this.categories.forEach( category => {
  this.categoryNames.push(category.name);
  });
});

}

});

}

Upvotes: 2

Jameel Moideen
Jameel Moideen

Reputation: 7931

Your implementation of forkjoin looks fine to me. But one problem I can see in your code is , you are iterating the categories outside of the getCategoryDetails callback. Since it is asynchronous , you should always ensure you are getting the categories before you do the iteration. For that you should move the code for iterating the categories to the successful callback function.

ngOnInit() {
    const id = parseInt(this.route.snapshot.paramMap.get('categoryId'), 10);
    this.store.dispatch(new fromCategory.LoadCategoryDetails(id));

    this.store.select(getCategoryDetails)
              .subscribe((data) => {
                this.categoryDetails = data[0];
                this.journeys = data[1];
                this.categories = data[2];

this.categories.forEach( category => {
      this.categoryNames.push(category.name);
    });
              });

    // filter only category name
    // problem

}

Upvotes: 0

Related Questions