Angular: 如何使用服务从服务器获取数据并存储在数组中?
Angular: How to use a Service to fetch data from server and store in an array?
我有一项服务在 https://pokeapi.co/api/v2/pokemon/
调用 PokéAPI。
如果您没有指定想要 return 的 Pokemon,API 将 return 一个分页的资源列表,其中包含 Pokemon 的 URL。
https://pokeapi.co/docs/v2#pokemon-section
我想将该 URL 列表存储在我的服务的本地数组中。
我试过:
getListOfPokemonUrls(): Observable<any> {
return this.http.get<any>(this.pokeApiUrl)
.pipe(
map((response: any[]) => this.pokemonResources = response.results)
);
}
在我的构造函数中(用于测试目的):
const y = this.getListOfPokemonUrls();
但是,当我跨过该函数时 this.pokemonResources
数组为空。
要点
- 使用可观察对象时,请务必
subscribe()
。
- 与其将服务器响应存储在局部变量中,不如 return 数据以便订阅 Observable 的调用者可以决定如何处理数据。这样做的好处是异步过程一完成,数据就立即可用。
查看工作 Stackblitz Demo。
关于 StackBlitz 演示的注释
- 创建了一个 Angular 服务
PokeAPIService
在构造函数中调用 PokeAPI 服务器。
constructor(private http: HttpClient) {
this.getListOfPokemonUrls().subscribe(
(results: Array<Pokemon>) => {
for(let p of results) {
this.pokemons.push(p)
}
}
)
}
请注意 getListOfPokemonURLs
return 的结果的更新实现,以便可以在对 subscribe()
的调用中处理它们。
- 为
Pokemon
和 PokeAPIResponse
定义的接口:
export interface Pokemon {
name: string,
url: string
}
interface PokeAPIResponse {
count: number,
next: string,
previous: string,
results: Array<Pokemon>
}
- 使用新的接口类型更新
getListOfPokemonUrls()
并修改 RxJS map
以便 response.results
直接 returned。
private getListOfPokemonUrls(): Observable<Array<Pokemon>> {
return this.http.get<any>(POKEAPI_URL)
.pipe(
map((response: PokeAPIResponse) => response.results)
);
}
作为参考,PokeAPI 服务器响应:
curl https://pokeapi.co/api/v2/pokemon/
Returns 以下回复:
{
"count":1050,
"next":"https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20",
"previous":null,
"results":[
{"name":"bulbasaur","url":"https://pokeapi.co/api/v2/pokemon/1/"},
{"name":"ivysaur","url":"https://pokeapi.co/api/v2/pokemon/2/"},
{"name":"venusaur","url":"https://pokeapi.co/api/v2/pokemon/3/"},
{"name":"charmander","url":"https://pokeapi.co/api/v2/pokemon/4/"},
{"name":"charmeleon","url":"https://pokeapi.co/api/v2/pokemon/5/"},
{"name":"charizard","url":"https://pokeapi.co/api/v2/pokemon/6/"},
{"name":"squirtle","url":"https://pokeapi.co/api/v2/pokemon/7/"},
...
我有一项服务在 https://pokeapi.co/api/v2/pokemon/
调用 PokéAPI。
如果您没有指定想要 return 的 Pokemon,API 将 return 一个分页的资源列表,其中包含 Pokemon 的 URL。
https://pokeapi.co/docs/v2#pokemon-section
我想将该 URL 列表存储在我的服务的本地数组中。
我试过:
getListOfPokemonUrls(): Observable<any> {
return this.http.get<any>(this.pokeApiUrl)
.pipe(
map((response: any[]) => this.pokemonResources = response.results)
);
}
在我的构造函数中(用于测试目的):
const y = this.getListOfPokemonUrls();
但是,当我跨过该函数时 this.pokemonResources
数组为空。
要点
- 使用可观察对象时,请务必
subscribe()
。 - 与其将服务器响应存储在局部变量中,不如 return 数据以便订阅 Observable 的调用者可以决定如何处理数据。这样做的好处是异步过程一完成,数据就立即可用。
查看工作 Stackblitz Demo。
关于 StackBlitz 演示的注释
- 创建了一个 Angular 服务
PokeAPIService
在构造函数中调用 PokeAPI 服务器。
constructor(private http: HttpClient) {
this.getListOfPokemonUrls().subscribe(
(results: Array<Pokemon>) => {
for(let p of results) {
this.pokemons.push(p)
}
}
)
}
请注意 getListOfPokemonURLs
return 的结果的更新实现,以便可以在对 subscribe()
的调用中处理它们。
- 为
Pokemon
和PokeAPIResponse
定义的接口:
export interface Pokemon {
name: string,
url: string
}
interface PokeAPIResponse {
count: number,
next: string,
previous: string,
results: Array<Pokemon>
}
- 使用新的接口类型更新
getListOfPokemonUrls()
并修改 RxJSmap
以便response.results
直接 returned。
private getListOfPokemonUrls(): Observable<Array<Pokemon>> {
return this.http.get<any>(POKEAPI_URL)
.pipe(
map((response: PokeAPIResponse) => response.results)
);
}
作为参考,PokeAPI 服务器响应:
curl https://pokeapi.co/api/v2/pokemon/
Returns 以下回复:
{
"count":1050,
"next":"https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20",
"previous":null,
"results":[
{"name":"bulbasaur","url":"https://pokeapi.co/api/v2/pokemon/1/"},
{"name":"ivysaur","url":"https://pokeapi.co/api/v2/pokemon/2/"},
{"name":"venusaur","url":"https://pokeapi.co/api/v2/pokemon/3/"},
{"name":"charmander","url":"https://pokeapi.co/api/v2/pokemon/4/"},
{"name":"charmeleon","url":"https://pokeapi.co/api/v2/pokemon/5/"},
{"name":"charizard","url":"https://pokeapi.co/api/v2/pokemon/6/"},
{"name":"squirtle","url":"https://pokeapi.co/api/v2/pokemon/7/"},
...