我无法解析数据并转换为平面列表

时间:2019-04-12 05:27:46

标签: angular typescript rxjs observable

使用ngrx,我从存储中获取了两个数据集。

  private getCatalog() {
    this.catalogStore.select(CatalogStoreSelectors.selectAllCatalogsLoadSuccess)
      .pipe(
        takeWhile(() => this.alive),
        take(1),
        filter(loadSuccess => !loadSuccess),
        tap(() => this.catalogStore.dispatch(new CatalogStoreActions.LoadAllAction())),
      ).subscribe();

    this.catalogs$ = this.catalogStore.select(CatalogStoreSelectors.selectAllCatalogs);
  }

catalog$将是Observable<ViewCatalog[]> 这是第一个数据集。

view-catalog.ts

export declare class ViewCatalog {
    code: string;
    title: string;
    lastModified: string;
}

对于每个catalog,您也可以通过catalog code来请求其商品

  private getCatalogItems(catalogCode: string) {
    this.catalogStore.dispatch(new CatalogStoreActions.GetCatalogItems({catalogCode: catalogCode}));

    this.catalogItemsStore.select(CatalogItemStoreSelector.selectLoadingByCatalogSuccess)
      .pipe(
        takeWhile(() => this.alive),
        take(1),
        filter(loadSuccess => !loadSuccess),
        tap(() => this.catalogItemsStore.dispatch(new CatalogItemStoreAction.LoadByCatalog({catalogCode: catalogCode}))),
      ).subscribe();

    this.catalogItems$ =  this.catalogItemsStore.select(CatalogItemStoreSelector.selectByCatalogCode(catalogCode));
  }

这是第二个数据集。

public catalogItems$: Observable<CatalogItem[]>;

CatalogItem.ts

export class CatalogItem {
  constructor(public code: string,
              public catalogCode: string,
              public title: string,
              public data: object) {
  }
}

我需要将所有这些数据合并到一个看起来像这样的普通平面列表中:

[
  catalog: {
    code: "Code 1",
    title: "Catalog title 1",
    lastModifie": "",
    parent: null,
    hasChildren: true
  }
  catalog-item: {
    code: "CatalogItem 1",
    catalogCode: "Code 1",
    parent: "Code 1",
    hasChildren: false,
    title: "CatalogItem title 1"
  },
  catalog-item: {
    code: "CatalogItem 2",
    catalogCode: "Code 1",
    parent: "Code 1",
    hasChildren: false,
    title: "CatalogItem title 2"
  },
  catalog: {
    code: "Code 2",
    title: "Catalog title 2",
    lastModifie": "",
    parent: null,
    hasChildren: true
  },
  catalog-item: {
    code: "CatalogItem 1",
    catalogCode: "Code 2",
    parent: "Code 2",
    hasChildren: false,
    title: "CatalogItem title 1"
  },
  catalog-item: {
    code: "CatalogItem 2",
    catalogCode: "Code 2",
    parent: "Code 2",
    hasChildren: false,
    title: "CatalogItem title 2"
  },
]

有人可以帮助实现这一目标吗?

1 个答案:

答案 0 :(得分:0)

这里是您的简化示例。它使用模拟来模仿目录和项目提取。

我已尝试根据需要添加尽可能多的评论。

总体思路是:

  1. 获取所有目录

  2. 为每个目录获取其项目,然后将它们放入具有目录的数组中

  3. 然后将所有这些数组合并为一个

const { of, combineLatest } = rxjs;
const { delay, switchMap, map } = rxjs.operators;

// 1. fetch all catalogues
// Observable<ViewCatalog[]>
getCatalogues().pipe(
  // chain to fetching items Observables
  switchMap(catalogues => {
    // 2. turn _each catalogue entry_ into
    // [ ViewCatalog, CatalogItem, CatalogItem ... ]
    // results: Observable<(ViewCatalog|CatalogItem)[]>[]
    const results = catalogues.map(
      cat => getItemsForCatalogue(cat.code).pipe(
        // now, merge the ViewCatalog entry
        // with the CatalogItem[] items for this catalogue
        map(items => [cat, ...items])
      )
    ); 

    // 3. use combineLatest to take the latest emissions from the store
    return combineLatest(
      results,
      // and project _each result_ into one array
      // `catsWithItems` here is of type `(ViewCatalog|CatalogItem)[][]`
      (...catsWithItems) => [].concat(...catsWithItems)
    );
  })
)
.subscribe(console.log)


// MOCKS
// getCatalogues(): Observable<ViewCatalog[]>
function getCatalogues(){
  const catalogues =
    [ { code: 1, name: 'cat-1' }
    , { code: 3, name: 'cat-3' }
    , { code: 5, name: 'cat-5' }
    ]

  return of(catalogues).pipe(delay(300));
}

// getItemsForCatalogue(catalogCode: number): Observable<CatalogItem[]>
function getItemsForCatalogue(catalogCode){
  const catalogueItems =
    [ { catalogCode: 1, name: 'item-1' }
    , { catalogCode: 1, name: 'item-2' }
    , { catalogCode: 5, name: 'item-3' }
    ]

  const items = catalogueItems.filter(
      item => item.catalogCode == catalogCode
    );

  return of(items).pipe(delay(300));
}
<script src="https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js"></script>

希望这会有所帮助