Как упростить вложенный вызов подписки ajax для Angular 6 - PullRequest
0 голосов
/ 22 октября 2018
getBudgetMap(budgetMonthID){
        this.rows = [];
        this.categoryService.getCategory(budgetMonthID).subscribe(category =>{
            this.categoryList = category;
            this.categoryList.forEach(category => {

                this.transactionService.getTransaction(budgetMonthID, category.id).subscribe(transaction => {
                    this.rows = this.rows.concat(transaction);
                })

            })
        )
    }

Чтобы сделать это проще, у меня есть вызов вложенной службы ajax (http.get), первый из которых (getCategory) возвращает список категорий на budgetMonthID.Количество категорий варьируется.Затем каждая категория будет делать второй вызов getTransaction, чтобы получить все транзакции, принадлежащие каждой категории.Приведенный выше код работает нормально, но я читал о map, flapMap, pipe для Angular , я просто не могу понять, как изменить этот неприятный код.Спасибо

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Это действительно требует некоторых знаний rxjs.

this.categoryService.getCategory(budgetMonthID).pipe(
  tap((categories) => this.categoryList = categories),
  mergeMap((categories) => zip(
    ...categories.map(
      (category) => this.transactionService.getTransaction(budgetMonthID, category.id)
    )
  )
).subscribe((rows) => {
  this.rows = rows;
});

Для начала мы используем нажмите , чтобы сохранить категории в categoryList.Это оператор, который просто выполняет функцию, но не влияет на поток в конвейере.

После этого мы используем mergeMap , который выбирает категории и возвращает другое наблюдаемое.В этом случае zip, который ожидает завершения всех параметров перед отправкой в ​​виде массива, который будет выбран подписчиком.

Вы также можете попытаться получитьпосмотри на встроенную async трубу от угловой.Это устраняет необходимость отмены подписки внутри вашего компонента и сохраняет его в чистоте.Это изменит ваш код на это:

this.categoryList$ = this.categoryService.getCategory(budgetMonthID).pipe(
  shareReplay(1)
);

this.rows$ = this.categoryList$.pipe(
  mergeMap((categories) => zip(
    ...categories.map(
      (category) => this.transactionService.getTransaction(budgetMonthID, category.id)
    )
  )
);

В вашем шаблоне вы можете получить к нему следующий доступ:

<div *ngFor="let category of categoryList$ | async"></div>
<div *ngFor="let row of rows$ | async"></div>
0 голосов
/ 22 октября 2018

Вы можете использовать rxjs operators, который имеет дело с асинхронным вызовом.Чтобы быть осторожным, вы должны использовать switchmap или flatmap или mergemap.Код может быть предоставлен, однако вы столкнетесь с той же проблемой в будущем снова.Поэтому я бы посоветовал вам сэкономить время, чтобы понять, как работает оператор rxjs.

Пожалуйста, пройдите через это - https://www.learnrxjs.io/operators/transformation/switchmap.html

...