angular - 在 Angular 中使用 Observables 返回循环的 API 调用值
问题描述
我试图让一个循环返回一个 API 调用。使用 Spotify API,我可以从名称中生成艺术家的 id,因此在前面的代码中,我生成了一个名称列表,保存在一个数组中。出于测试目的,我使用了一个虚拟数组,该数组与之前的 API 调用将返回的值相同。
getAllSpotifyArtistIds(){
let dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];
for (let i = 0; i < dummyArtistList.length; i++) {
this.artistToQuery = dummyArtistList[i];
this.generateArtistIdFromArtist(dummyArtistList[i]).subscribe((response) => {
this.newProperty.push(response); //this is a class property I'm hoping to populate with this response.
})
}
}
函数 generateArtistIdFromArtist(artistName: string) 每次调用都会返回一个值,即从 Spotify 的 API 中查询的艺术家 ID。
从 spotify 生成 Arist ID 的代码如下:
generateArtistIdFromArtist(artistName){
return this.spotifyService.getToken().pipe(
flatMap((accessTokenResponse) => {
return this.spotifyService.searchArtistID(artistName, accessTokenResponse.access_token)
.map((response) => {
response.artists.items.forEach((spotifyArtist) => {
this.spotifyArtistListFromQuery.push(spotifyArtist.name);
});
const artistMatchIndexPosition = this.spotifyArtistListFromQuery.findIndex((artistToQueryNow) => {
return artistToQueryNow === artistName;
});
//Spotify returns multiple artists with similar names, so check for identical match
if (artistMatchIndexPosition >= 0 ){
this.artistIdListFromSpotify.push(response.artists.items[artistMatchIndexPosition].id)
return response.artists.items[artistMatchIndexPosition].id;
// finally return the id of the artist if there's a match
}
});
})
);
}
我已经尝试将 setTimeout() 放在不同的地方,但我认为我对异步编码的理解不够好,无法真正知道我在做什么。我想也许强迫一些暂停可能会让循环赶上。在这一点上,我只得到 3 个值。
我希望 dummyArtistList 中的每个艺术家都会返回 Spotify 结果,但它只返回一些,而且它们在某种程度上是不正确的。
如果您将单个名称传递给它,这将非常有效,但是如果您开始执行多个名称,则循环失败,并且在三个上它会给出完全错误的结果。我是编码新手,尤其是异步,所以我很难理解为什么我不能让循环等待 API 调用完成 observables。我确信这与循环本身不是异步的事实有关,并且 API 调用是,任何帮助解决这个问题将不胜感激。
解决方案
您也可以使用forkJoin来执行此操作,因为您希望将所有结果都放在一个数组中。
将所有内容保存在一个临时数组中并使用运算符observables
订阅它forkJoin
getAllSpotifyArtistIds(){
let dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];
let artistSet = [];
for (let i = 0; i < dummyArtistList.length; i++) {
this.artistToQuery = dummyArtistList[i];
artistSet.push(this.generateArtistIdFromArtist(dummyArtistList[i]))
}
forkJoin(...artistSet).subscribe((response) => {
//Here response is an array and you can simply assign
this.newProperty = response;
})
}