使用forkJoin

时间:2019-09-25 17:41:39

标签: angular rxjs

我有类似的数据:

[
  {
    id: 1,
    pets: [
      {
        id: 11,
        pet: 'Zebra'
      },
      {
        id: 12,
        pet: 'Giraffe'
      }
    ]
  }
]

我从get请求获得。对于in和array以及其中pets数组中的每个项目,我都需要根据id从另一个端点获取mood的{​​{1}},例如,返回:

pet

因此请求后最终结果将如下所示:

{
  id: 11,
  mood: 'hungry'
}

我尝试对所有[ { "id": 1, "pets": [ { "id": 11, "pet": "Zebra", "mood": "hungry" }, { "id": 12, "pet": "Giraffe", "mood": "happy" } ] } ] 使用forkJoin,但无法使其正常工作。下面是Stackblitz的一种尝试:

pets

它正确地返回了3个外部对象,但是看起来它们都是相同的对象。如何获得正确的结果?预先感谢,这是Stackblitz:https://stackblitz.com/edit/angular-ttpcvu?file=src%2Fapp%2Fapp.component.ts

2 个答案:

答案 0 :(得分:1)

尝试一下:

  getCombined() {
    return forkJoin( // don't need the of and whatnot.
      this.parent.map(family => {
        return forkJoin(
          family.pets.map(pet => {
            return this.getMood(pet.id).pipe(
              map(mood => {
                pet.mood = mood.mood; //assign mood
                return pet; // return populated pet.
              })
            );
          })
        ).pipe(
          map(pets => {
            family.pets = pets; // assign the pets here
            return family; // return populated family.
          })
        )
      })
    );
  }

闪电战:https://stackblitz.com/edit/angular-uwqclm?file=src/app/app.component.ts

您需要为外部集和内部集创建一个forkjoin才能正确执行,并且需要在正确的位置进行分配。

答案 1 :(得分:0)

在下面的代码中,我们将对象数组作为可观察流进行流处理,然后 再次传送宠物,并创建伪造的Obserbale(api调用),然后将响应映射到宠物属性,然后再次将所有宠物与它们各自的所有者一起制作。

const { fromEvent, merge, of, from } = rxjs;
const { map, filter, concatMap, toArray, tap, delay, concatAll, mergeMap,mergeAll } = rxjs.operators;
// Write TypeScript code!
const appDiv = document.getElementById('app');
appDiv.innerHTML = `<h1>if you dont want Asynchronous request then you can use concat instead of merge</h1>`;
console.clear();

const data$ = of([{
  id: 1, pets: [
    { id: 11, pet: 'Zebra' },
    { id: 12, pet: 'Giraffe' }
  ]
},
{
  id: 2, pets: [
    { id: 21, pet: 'Zebra' },
    { id: 22, pet: 'Giraffe' }
  ]
}
])
const q = (x) => {
  // Fake http call 
  // you can make your api call here 
  const oneSecondSource$ = of(x['id']).pipe(delay(1 * x.id))
  return oneSecondSource$.pipe(map(abs => {
    const res = Math.floor(Math.random() * Math.floor(1)) === 0 ? 'hungry' : 'happy';
    // and map the resulatant mood
    return { ...x, mood: res }
  }));
}

const p = (obj) => {
  // mapping each
  return from(obj.pets).pipe(mergeMap(q), toArray(), map(a => {
    return { id: obj.id, pets: a }
  }))
}
const example$ = data$.pipe(mergeMap(a => from(a).pipe(map(p))),
  mergeAll(),
  toArray()
);
example$.subscribe(console.log)
<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>

<div id="app"></div>

这里是stackblitz solution you can refer