【问题标题】:Angular Loop on fetched observable array data and fetch another array of data in itAngular Loop 在获取的可观察数组数据上并在其中获取另一个数据数组
【发布时间】:2021-10-09 19:06:33
【问题描述】:

您好,我有一个 API 调用 getItems(),它返回如下数据:

[
 {
   name: 'item1',
   materials: [
     1,
     2,
     3,
   ],
 },
 {
   name: 'item2',
   materials: [
     2,
     3,
     6,
   ],
 }
 ...
]

另一个 API 调用 getMaterial(id) 会返回这样的材料数据:

{
  name: 'mat1',
  img: '/img.jpg'
}

我试图实现的是使用材料数据获取所有项目数据。我设法获得了所有可观察到的材料要求,但我不知道之后该做什么。

这就是我到目前为止所做的:

public getAllItemsData(): Observable<any> {
  return getItems().pipe(
    map((list: items[]) => {
      return list.map(item => {
        const allMat = item.materials.map(m => getMaterial(m))

        return forkJoin(allMat).pipe(
          map(data => {
            return {
              ...item,
              materials: data
            }
          })
        )
      })
    }),
  );
}

但它不起作用。感谢您的帮助。

【问题讨论】:

    标签: angular typescript rxjs


    【解决方案1】:

    试试这个。 使用switchMapmergeMapfromforkJoin

    getItems()
      .pipe(
        switchMap((items) =>
            // for each items
          from(items).pipe(
           // merge map to run parallel for each items
            mergeMap(({ materials, ...item }) =>
            // wait to retrive all materials details of current item at mergeMap
            // after completing use map to map item with retrived materials 
              forkJoin(
                materials.map((m) => this.getMaterial(m))
              ).pipe(map((materialDetails) => ({ ...item, materials: materialDetails })))
            )
          )
        )
      )
      .subscribe((result) => {
        console.log(result);
      });
    

    【讨论】:

    • 有没有办法在没有 switchMap 的情况下做到这一点,让它更容易(我不应该)我忽略了我正在使用 firestore valuechange 这意味着有一个活动流,我觉得就像在这个解决方案中导致问题的 switchMap 一样!我没有错误,但没有输出数据。
    • 如果你可以在 stackblitz 上生成。我可以帮你轻松
    • error Can't find package:@angular/fire.. 你可以分享一些 JSON 数据吗?或者我应该用来自question 的数据提供演示示例?
    【解决方案2】:

    与上面的非常相似,只是嵌套的管道更少

    interface Item {
        name: string;
        materials: number[];
    }
    
    interface MaterialData {
        name: string;
        img: string;
    }
    
    public getAllItemsData() {
        return getItems().pipe(
            switchMap((items: Item[]) => from(items)), // use 'from' to deal with one Item at a time
            mergeMap(({ materials, name }: Item) =>
                forkJoin(materials.map((mat) => getMaterial(mat))) // create array of observables using map, and pass into forkJoin 
                    .pipe(
                        map((materials) => ({ name, materials })), // reconstruct object
                    ),
            ),
            toArray(), // collect all emissions and output as an array
        );
    };
    

    【讨论】:

    • 有没有办法在没有 switchMap 的情况下做到这一点,让它更容易(我不应该)我忽略了我正在使用 firestore valuechange 这意味着有一个活动流,我觉得就像在这个解决方案中导致问题的 switchMap 一样!我没有错误,但我没有输出数据
    【解决方案3】:

    我认为您只是缺少最终的合并/forkJoin 来订阅您创建的可观察对象数组。

    public getAllItemsData(): Observable<any> {
    
      return getItems().pipe(
    
        map((list: items[]) => 
          list.map(item => 
            forkJoin(
              item.materials.map(m => getMaterial(m))
            ).pipe(
              map(materials => ({
                ...item,
                materials
              }))
            )
          )
        ),
    
        // Subscribe to the list created above
        mergeMap((list:Observable<any>[]) => forkJoin(list))
    
      );
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      • 2018-07-11
      • 2019-06-04
      • 1970-01-01
      相关资源
      最近更新 更多