如何在Angular服务中使用RxJS处理多个api调用?

时间:2018-06-29 20:25:25

标签: angular rxjs

问题:我想从《星球大战》 Api(SWAPI)获取数据。我想进行初始的http调用,然后在同一调用中,从2个其他api调用中获取值。 Swapi返回json对象,但其值也是其api其他部分的网址。

当前,此代码有效,但我只能检索角色对象,然后再检索homeworld对象。

这是我的代码:

question.service.ts

  getCharacter() {
    const random = Math.floor(Math.random() * 10) + 1;

   let characterUrl = `https://swapi.co/api/people/${random}/`;

   this.http.get(characterUrl).pipe(
    mergeMap((character:any) => {

      this.character = character;

    //I tried using forkJoin(this.http.get(character.species), this.http.get(character.homeworld)), but it wasn't working.

    //In total, I want to get the original character object, and also the species/homeworld values. 

      return this.http.get(character.homeworld);

    })
    //logs out the homeworld value, but I'd also like the species value.
  ).subscribe(v => console.log(v))

  }

这是我要从中重构的代码:

question.component.ts

   this.questionService.getCharacter().subscribe((character: any) => {
   console.log(character)
    this.http.get(character.homeworld).subscribe((homeworld: any) => {
      this.loadedCharacter = character;

      this.loadedCharacter.homeworld = homeworld.name;

        this.http.get(character.species[0]).subscribe((species: any) => {
        this.loadedCharacter.species = species.name;
        this.makeQuestions();
    });
    });
  });

SWAPI示例json对象:

{
    "birth_year": "19 BBY",
    "eye_color": "Blue",
    "films": [
        "https://swapi.co/api/films/1/",
        ...
    ],
    "gender": "Male",
    "hair_color": "Blond",
    "height": "172",
    "homeworld": "https://swapi.co/api/planets/1/",
    "mass": "77",
    "name": "Luke Skywalker",
    "skin_color": "Fair",
    "created": "2014-12-09T13:50:51.644000Z",
    "edited": "2014-12-10T13:52:43.172000Z",
    "species": [
        "https://swapi.co/api/species/1/"
    ],
    "starships": [
        "https://swapi.co/api/starships/12/",
        ...
    ],
    "url": "https://swapi.co/api/people/1/",
    "vehicles": [
        "https://swapi.co/api/vehicles/14/"
        ...
    ]
}

1 个答案:

答案 0 :(得分:3)

您在正确的轨道上,差点就走了。物种是一个数组,因此,如果物种类型不止一种,您还需要在其中另外一个forkJoin

return this.http.get(characterUrl)
.pipe(
  mergeMap((character: any) => {
    return forkJoin(
      // Get the homeworld
      this.http.get(character.homeworld),
      // Another forkJoin for the species
      forkJoin(
        character.species.map(type => {
          return this.http.get(type)
        })
      )
    ).pipe(
      // Transform to a consumable object
      map(d => {
        return  {
          character: character,
          homeworld: d[0],
          species:   d[1]
        }
      })
    )
  })
)

作为示例,这将返回具有以下属性的对象:

character: Object
homeworld: Object
species: Array[1]

这里是StackBlitz demo