我怀疑我根本上误解了Javascript的承诺,有什么想法吗?
我有一个很漂亮的函数,它可以查询一个包含以下音乐的数据库:
function searchDatabaseForTrack(query,loadedResults){
loadedResults = loadedResults || [];
desiredResults = 100;
if (loadedResults.length < desiredResults) {
try {
databaseApi.searchTracks(query, {"offset":loadedResults.length, "limit":"50", }).then(function(data){
i=0
if (data.tracks.items.length == 0) {
console.log(`Already loaded all ${loadedResults.length} tracks!`)
console.log(loadedResults)
return loadedResults;
}
else {
for (thing in data.tracks.items){
loadedResults.push(data.tracks.items[i]);
i=i+1;
}
console.log(loadedResults.length, " tracks collected");
searchDatabaseForTrack(query,loadedResults)
}
});
} catch(err) {
console.log("ERROR!", err)
console.log(loadedResults)
return loadedResults;
}
} else {
console.log(loadedResults)
return loadedResults;
}
}
稍后,我尝试调用并使用检索到的数据。
function getArtistTracks(artistName){
searchDatabaseForTrack(artistName).then(function(data){
console.log(songs);
songs.sort(function(a,b){
var c = new Date(a.track.album.release_date);
var d = new Date(b.track.album.release_date);
return d-c;
});
console.log("songs", songs);
var newsongs=[];
i=0
for (song in songs) {
newsongs.push(songs[i].track.uri);
i++
};
return newsongs;
});
}
我尝试做的是让第二个函数“getArtistTracks”等待第一个函数中查询的完成。现在我可以直接调用databaseapi.searchtracks,但是每个结果只能返回50个音轨--这有点让我受不了。
SearchDatabaseForTrack()。then(。。。)
不能工作,因为SearchDatabaseForTrack()
没有返回承诺,因此您可以返回承诺或使用异步函数。
您可以在for
循环中简单地调用DatabaseAPI
,而不是递归函数,
DesiredResult
应该是一个参数,
async function searchDatabaseForTrack(query, desiredResults){
let loadedResults = [], data, currOffset = 0;
const iterations = Math.ceil(desiredResults / 50);
for(let n = 0 ; n < iterations; n++){
cuurOffset = n * 50;
data = await databaseApi.searchTracks(query, {"offset":currOffset, "limit":"50", });
if (data.tracks.items.length == 0) {
console.log(`Already loaded all ${loadedResults.length} tracks!`)
console.log(loadedResults)
return loadedResults;
}
else {
loadedResults = loadedResults.concat(data.tracks.items);
console.log(loadedResults.length, " tracks collected");
}
}
return loadedResults;
}
只要您添加.catch()
来处理错误(如上一个答案中提到的),其余的就可以了,这些错误是自动抛出的,而不需要try/catch
块:
function getArtistTracks(artistName, 100){
searchDatabaseForTrack(artistName).then((songs) => {
// your previous code
})
.catch((err) => {
// handle error
});
});
让SearchDatabaseForTrack
在获得所有结果后使用Promise.all
返回LoadedResults
。另外,请确保不要像使用thing
那样隐式地创建全局变量。例如,尝试这样的方法:
async function searchDatabaseForTrack(query) {
const desiredResults = 100;
const trackPromises = Array.from(
({ length: Math.ceil(desiredResults / 50) }),
(_, i) => {
const offset = i * 50;
return databaseApi.searchTracks(query, { offset, limit: 50 });
}
);
const itemChunks = await Promise.all(trackPromises);
const loadedResults = itemChunks.reduce((a, { tracks: { items }}) => (
[...a, ...items]
), []);
return loadedResults;
};
和
searchDatabaseForTrack(artistName).then((loadedResults) => {
// do stuff with loadedResults
})
.catch((err) => {
console.log("ERROR!", err)
// handle error
});