Как сделать несколько HTTP-вызовов в Angular6, используя forkJoin и ngrx? - PullRequest
0 голосов
/ 26 сентября 2018

Сценарий

В моем приложении angular6 у меня есть три категории: catA, catB, catC. Каждая категория нуждается в данных от 3 API .При нажатии на любую категорию он загружает компонент CategoryDetailsComi, и я отправляю действие (LoadCategoryDetails).

Я реализовал forjoin для выполнения параллельных вызовов API (в процессе обслуживания), а также resolver для обеспечения выполнения всех вызовов, только тогда компонент должен быть загружен.

Проблема

  • При нажатии catA (или перезагрузке страницы) массив categoryNames пуст
  • При нажатии catB (вторая маршрутизация), массив CategoryNames показывает список предыдущей категории (catA)

Возможно, один из вызовов API требует времени.и мой распознаватель не настроен должным образом.

Вопрос

Как настроить эффекты и распознаватель ??

Как использовать forkjoin для выполнения нескольких вызовов и отправки данных компоненту?

Код

  1. dipatch action и подписка на селектор

    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. эффекты (ищите службу действий и вызовов)

    @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. сервисная функция, выполняющая несколько вызовов и использующая 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. распознаватель

    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);
        }
    }

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Рефакторинг вашего кода, чтобы НЕ использовать route.snapshot, и посмотреть, исправит ли это.

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);
  });
});

}

});

}
0 голосов
/ 26 сентября 2018

Ваша реализация forkjoin выглядит хорошо для меня.Но одна проблема, которую я вижу в вашем коде, заключается в том, что вы перебираете категории вне обратного вызова getCategoryDetails .Поскольку он асинхронный, вы всегда должны убедиться, что получаете категории перед выполнением итерации.Для этого вам следует переместить код для итерации категорий в функцию успешного обратного вызова.

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

}
...