Как провести рефакторинг HttpRequests во вложенных циклах for, которые используют подписку? - PullRequest
0 голосов
/ 10 июля 2020

у нас есть REST-API, который является внешним интерфейсом c, что означает, что он всегда отправляет IRI своим вложенным ресурсам. Итак, чтобы получить некоторые данные, вам всегда нужно выполнять несколько HTTP-вызовов (сначала получить родительский ресурс, затем его дочерние ресурсы и т. Д. c.) Таким образом, каждая страна имеет список связанных записей. Каждая запись связана с продуктом, у которого есть IRI для ресурса категории.

export interface Country {
  countryId: number;
  name: string;
  code: string;
  projects: string[]; //contains an array of IRIs for the project resources
  entries: string[];
}

export interface Entry {
  entryId: number,
  country: string,
  information: string,
  strategy: string,
  action: string,
  user: string,
  product: string,
  salesStatus1: string,
  salesStatus2: string,
  salesStatus3: string,
  salesStatus4: string,
  salesStatus5: string,

}

export interface Product {
  productId: number,
  productName: string,
  sharepointId: string,
  category: string,
  plmId: string,
  productStatus1: string,
  productStatus2: string,
  productStatus3: string,
  productStatus4: string,
  productStatus5: string,
  productComponents: string[]
}

export interface Category {
  categoryId: number,
  name: string,
  children: string[]
}
export class Node {
  children: Node[] = [];
  name: string;
  isProduct: boolean;
}

Итак, чтобы использовать все данные, необходимые для отображения дерева навигации, я написал следующий код:

ngOnInit() {
    let nodes: Node[] = new Array<Node>();
    this.countriesService.getAll()
      .subscribe(
        (countries) => {
          for (let country of countries) {
            let countryNode = new Node();
            countryNode.name = country.name;
            countryNode.isProduct = false;
            for (let entryUrl of country.entries) {
              this.entriesService.getByUrl(entryUrl).subscribe(
                (entry) => {
                  this.productsService.getByUrl(entry.product).subscribe(
                    (product) => {
                      this.categoryService.getByUrl(product.category).subscribe(
                        (category) => {
                          let categoryNode = new Node();
                          categoryNode.name = category.name;
                          categoryNode.isProduct = true;
                          countryNode.children.push(categoryNode);
                          for (let childrenUrl of category.children) {
                            this.categoryService.getByUrl(childrenUrl).subscribe(
                              (childCategory) => {
                                let categoryChildNode = new Node();
                                categoryChildNode.name = childCategory.name;
                                categoryChildNode.isProduct = false;
                                categoryNode.children.push(categoryChildNode);
                              }
                            )
                          }
                        }
                      )
                    }
                  )
                }
              )
            }
            nodes.push(countryNode);
          }
          this.dataChange.next(nodes);
        }
      );
  }

Однако, поскольку я немного новичок в Angular и rx js, у меня возникают проблемы с "ждать", пока все вызовы не будут завершены и все данные (как их асинхронные) будут там (и поэтому дерево навигации всегда пропускает элементы). К тому же это некрасивое и плохое занятие. Итак, я хотел реорганизовать код для rx js -методов, однако я совершенно потерял, как даже начать с него, потому что после получения данных мне нужно повторить его снова, чтобы получить вложенные IRI ресурсов, а также создать узел объекты для древовидной навигации.

Не могли бы вы мне помочь, как реорганизовать этот код?

1 Ответ

0 голосов
/ 10 июля 2020

не уверен, что это может быть полезно, я объединил запросы с операторами rx js.

this.countriesService.getAll()
  .pipe(
    map((cs) => forkJoin(cs.map(c => {
      const countryNode = new Node();
      countryNode.name = c.name;
      countryNode.isProduct = false;

      return forkJoin(c.entries.map(entryUrl => this.entriesService.getByUrl(entryUrl)))
        .pipe(
          switchMap(entries => forkJoin(entries.map(entry => this.productsService.getByUrl(entry.product)))),
          switchMap(products => forkJoin(products.map(product => this.categoryService.getByUrl(product.category)))),
          switchMap(categories => forkJoin(categories.map(category => {
            const categoryNode = new Node();
            categoryNode.name = category.name;
            categoryNode.isProduct = true;

            return forkJoin(category.children.map(childrenUrl => this.categoryService.getByUrl(childrenUrl)))
              .pipe(
                map(cc => {
                  categoryNode.children = cc.map(childCategory => {
                    const categoryChildNode = new Node();
                    categoryChildNode.name = childCategory.name;
                    categoryChildNode.isProduct = false;
                    return categoryChildNode;
                  });
                  return categoryNode;
                })
              );
          }))),
          map(categoryNodes => {
            countryNode.children = categoryNodes;
            return countryNode;
          })
        );
    })))
  ).subscribe(countryNodes => {
    this.dataChange.next(countryNodes)
  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...