我正在尝试获取一个返回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调用以可观察对象完成。我确信这与以下事实有关:循环本身不是异步的,并且API调用是,对将其分类的任何帮助都将不胜感激。
答案 0 :(得分:0)
您需要的是一组可观察的数组,即来自rxjs的concat运算符,并对其进行订阅。了解有关concat here的更多信息。
您可以这样导入concat:
从'rxjs / operators'导入{concat};
getAllSpotifyArtistIds() {
const APICallArray = [];
const dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];
for (let i = 0; i < dummyArtistList.length; i++) {
this.artistToQuery = dummyArtistList[i];
APICallArray.push(this.generateArtistIdFromArtist(dummyArtistList[i]));
}
concat(...APICallArray).subscribe((res) => {
res.map((response) => {
response.artists.items.forEach((spotifyArtist) => {
this.spotifyArtistListFromQuery.push(spotifyArtist.name);
});
const artistMatchIndexPosition = this.spotifyArtistListFromQuery.findIndex((artistToQueryNow) => {
return artistToQueryNow === artistName;
});
if (artistMatchIndexPosition >= 0 ) {
this.artistIdListFromSpotify.push(response.artists.items[artistMatchIndexPosition].id);
this.newProperty.push(response.artists.items[artistMatchIndexPosition].id);
}
});
});
}
generateArtistIdFromArtist(artistName) {
return this.spotifyService.getToken().pipe(
flatMap((accessTokenResponse) => {
return this.spotifyService.searchArtistID(artistName, accessTokenResponse.access_token);
})
);
}
答案 1 :(得分:0)
您也可以使用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;
})
}
答案 2 :(得分:0)
由于@Ritesh的帮助,我得以弄清楚如何解决此问题。
最后两个功能是
generateArtistIdFromArtist(artistName) {
return this.spotifyService.getToken().pipe(
flatMap((accessTokenResponse) => {
return this.spotifyService.searchArtistID(artistName, accessTokenResponse.access_token);
})
);
}
,然后返回包含艺术家的信息数组,使用此调用,APICallArray本身实际上就已拥有该信息,无需明显地订阅。我仍然不完全了解这是什么产生的,但是我能够得到所有答案。
getAllSpotifyArtistIds() {
const APICallArray = [];
const dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];
const ArtistOutputArray = [];
for (let i = 0; i < dummyArtistList.length; i++) {
this.artistToQuery = dummyArtistList[i];
APICallArray.push(this.generateArtistIdFromArtist(dummyArtistList[i]));
}
for (let i = 0; i < APICallArray.length; i++) {
APICallArray[i].subscribe((response) => {
ArtistOutputArray.push(response);
});
}
return ArtistOutputArray;
}
谢谢@Ritesh!