消耗现有API的异步问题

时间:2018-12-28 09:31:38

标签: typescript rest api async-await

我实际上正在使用现有的Api做一个WebApp:PokéAPI 问题是,我想获得所有宠物小精灵的名字并在第一时间打印出来。而且有效!但是...没有秩序。我想要的是打印按ID排序的神奇宝贝清单(首先是bulbasaur,第二是ivysaure等),在这里有时ulbasaur是清单的第五,等等。我可以解决它,我认为与async并等待在互联网上寻找,但我可以使其起作用。

已经尝试了异步等待解决方案,但肯定是以错误的方式进行的。我不知道在哪里以及何时何地使用它们

=== data.service.ts ===

import { Injectable } from '@angular/core'
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  constructor(private http: HttpClient) { }

  getPokemons(id) {
    return this.http.get('https://pokeapi.co/api/v2/pokemon/' + id +'/')
   }
}

=== home.component.ts ===

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  pokemons: any = [];

  constructor(private data: DataService) { }

  async ngOnInit() {
    for(var i=1; i<152; i++){
      await this.data.getPokemons(i).subscribe(data => {
        this.pokemons.push(data)
    })}

   console.log(this.pokemons)
  }

}

=== home.component.html ===

<p>
  home works!
</p>

<ul *ngIf="pokemons">
  <li *ngFor="let u of pokemons">
      {{u.name}}
  </li>

</ul>

预计:球囊龙常春藤 当前:charmender beedrill ivysaur(随机顺序)

编辑: 所以我检查了您的解决方案,也许我听不懂,但是我做到了:

ngOnInit(){

forkJoin(
  [...Array(151)].map((_, i) => this.data.getPokemons(i + 1))
)
.subscribe(data => {
  this.pokemons = data;
  console.log(this.pokemons)
});
}

并在console.log上收到此错误:错误TypeError:“您在期望流的位置提供了'undefined'。您可以提供Observable,Promise,Array或Iterable。”

我认为问题出在地图函数中的“ _”,在互联网上搜索,没有找到类似的东西。我们同意我不需要编写loadAllAtOnce函数,这只是一个示例?我希望我不会在问您这个问题,但是[... Array(151)]。map是什么意思? (什么是“ ...”)

编辑:某些事情很奇怪。我在网站顶部的导航栏中创建了一个新组件,因为我的列表位于“主页”组件中,因此我想将其放置在另一个而不是主页中。只是为了测试,我也将列表放在了home组件中。 当我从一个组件切换到另一组件(从家到pokedex或从pokedex到家)时,我的列表排列得很好,就像我想要的那样。但是,当我刷新相同的组件时,列表不再井井有条。我不明白为什么,但是也许这种精度可以帮助您...

1 个答案:

答案 0 :(得分:0)

解决方案是一次拨打所有电话,然后通过 forkJoin 等待所有电话完成。它将以与您为 forkJoin 函数提供的可观察对象数组相同的顺序在数组中提供响应。

它看起来像这样:

loadAllAtOnce(values: number[]) {
  return forkJoin(
    values.map(x => of (x).pipe(delay(x)))
  ).pipe(
    tap(values => {
      console.log(values);

    })
  );
}

您可以看到一个完整的示例here

在您的情况下,代码如下所示:

forkJoin(
    Array(151) // make an empty array with length 152
      .fill(0) // fill it with zeros
      .map((_, i) => this.data.getPockemons(i + 1)) // _ means ignore the parameter
  )
  .subscribe(pockemons => {
    this.pockemons = pockemons;
    console.log(this.pokemons)
  });

您可以找到此here的示例。