代码之家  ›  专栏  ›  技术社区  ›  Dream_Cap

如何使用rxjs在角度服务中处理多个api调用?

  •  2
  • Dream_Cap  · 技术社区  · 8 年前

    问题:我想从星球大战api(swapi)获取数据。我想进行一个初始的http调用,然后在同一个调用中,从另外两个api调用中获取值。swapi返回一个json对象,但其值也是指向其api其他部分的url。

    目前,这段代码可以工作,但我只能检索character对象,然后检索homeworld对象。

    这是我的代码:

    问题.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))
    
      }
    

    这是我要重构的代码:

    问题.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 回复  |  直到 8 年前
        1
  •  3
  •   Michael Doye Björn Kaiser    8 年前

    你在正确的轨道上,几乎得到了它。物种是一个数组,所以你需要另一个 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