Angular 8 вложенных подписок - PullRequest
1 голос
/ 17 апреля 2020

Я делаю запрос на получение, чтобы получить роль пользователя.

private myOrders;
constructor(private userData: UserDataService) {
  this.userData.getUser().subscribe((user: any) => {
    //and then I'm doing a conditional get 
    if (user.role == "Admin") {
      this.userData.getAdminOrders().subscribe((adminOrders: any) => {
        this.myOrders = adminOrders
      });
    } else {
      this.myOrders = user.orders
    }
  });

Мое приложение правильно показывает только user.orders (заказы для обычных клиентов), но когда я с Учетная запись администратора показывает только загрузку первой страницы, но затем они исчезают.

Как мне управлять этими вложенными подписками? (Это http.get на моем userDataService)

Ответы [ 3 ]

2 голосов
/ 17 апреля 2020

В этом случае следует использовать один из операторов rx js.

Для этого случая я рекомендую вам flatMap :

private myOrders;
constructor(private userData: UserDataService) {
  this.userData.getUser().pipe(flatMap(user: any) => {
    if (user.role == "Admin") {
      return this.userData.getAdminOrders();
    } else {
      return of(user.orders)
    }
  }).suscribe((result) => {
        this.myOrders = result
    }
  );

Если user.role == "Admin" равно true, result будет результатом HTTP-запроса в this.userData.getAdminOrders(). В другом случае результат будет user.orders.

1 голос
/ 18 апреля 2020

Использует switchMap оператор и наблюдаемый iif и of

this.userData.getUser()
  .pipe(
    switchMap(({ role, orders }) =>
      iif(
        () => role === 'Admin',
        this.userData.getAdminOrders(),
        of(orders),
      ),
    ),
  )
  .subscribe(orders => (this.myOrders = orders));

никогда не используют подписку в другой подписке, потому что вы создаете утечки памяти, или для более чистого и лучшего решения используйте asyn c труба, как указано @ BizzyBob

1 голос
/ 17 апреля 2020

Вы можете избежать использования вложенных подписок, используя один из «операторов отображения более высокого порядка» LINK

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

switchMap будет «переключаться» на новую наблюдаемую при каждом получении нового значения. Поэтому, когда вы передаете «user», сопоставляете его с соответствующей наблюдаемой на основе user.role, он подписывается на него и испускает эти значения. Когда получено новое значение «user», оно отписывается от предыдущих наблюдаемых и подписывается на новое.

Кроме того, вместо подписки в вашем компоненте вы можете определить «myOrders» как Observable , на который вы можете подписаться в шаблоне, например:

public myOrders$ = this.userData.getUser().pipe(
    switchMap(user => { 
        return user.role = 'Admin' 
            ? this.userData.GetAdminOrders() 
            : of(user.orders));
        }
    );

Затем вы можете использовать async канал в вашем шаблоне. Это означает, что вам не нужно беспокоиться об управлении подписками в вашем компоненте.

<ul>
    <li *ngFor="order of myOrders$ | async">{{ order.description }}</li>
</ul>
...