我有一个 JavaScript 函数,它递归调用 Spotify API,以获取用户保存的歌曲的数据,例如曲目名称、专辑、添加日期等(调用限制为 50,所以我需要多次重复调用)。然后,它将数据处理为 .csv 格式以供用户下载。如下所示(它工作完全正常)。
async function repeatGet(url, tracksArray = [["Track", "Artist", "Album", "Date-Time Added", "Spotify Link"]]) {
tracksObject = await apiCall(url);
for (track of tracksObject.items) { tracksArray.push([track.track.name, track.track.artists[0].name, track.track.album.name, track.added_at, track.track.external_urls.spotify]) }//tracksTotal.push(track) }
if (tracksObject.next != undefined) { await repeatGet(tracksObject.next, tracksArray) }
return tracksArray
}
tracksArray = await repeatGet("https://api.spotify.com/v1/me/tracks?limit=50")
console.log(tracksArray);
let csvData = "sep=\t \n";
tracksArray.forEach(row => csvData += row.join("\t") + "\n")
console.log(csvData);
我尝试通过将调用的数据立即转换为.csv格式并连接到字符串(下面的代码)来提高效率:
async function repeatGet(url, csvData = "sep=\t \nTrack\tArtist\tAlbum\tDate-Time Added\tSpotify\tLink") {
tracksObject = await apiCall(url);
for (track of tracksObject.items) {
csvData += "\n" + track.track.name + "\t" + track.track.artists[0].name + "\t" + track.track.album.name
+ "\t" + track.added_at + "\t" + track.track.external_urls.spotify;
}
// console.log(csvData)
if (tracksObject.next != undefined) { await repeatGet(tracksObject.next, csvData) }
console.log(csvData,csvData.length);
return csvData;
}
csvData = await repeatGet("https://api.spotify.com/v1/me/tracks?limit=50");
出于未知原因,此代码仅返回第一个 api 调用中的 .csv 字符串(而不是与所有后续字符串组合的总字符串)。
我尝试通过在某些部分使用 console.log 来修复错误,并且当每个新调用通过时,代码都会正确附加到 csv。然而,在最后一次调用之后,一切都崩溃了,控制台立即返回每次后续调用发生时发生的所有日志(csv 字符串的大小不断增长),但不知何故以相反的顺序。有人有什么想法吗?谢谢。
第二个版本没有收集所有结果的原因是,现在您不会改变收集结果的结构(就像您对
tracksArray.push()
所做的那样),而是分配到局部变量(csv +=
)。后者创建一个新字符串并且不会改变任何内容。您永远无法实现递归调用会更改调用者 csv
字符串的内容;字符串是不可变的:无法创建一个函数来更改传递给它的字符串。
但正如评论中已经提到的,这种提高效率的努力并没有解决瓶颈。瓶颈是请求/响应延迟——客户端请求和接收服务器响应之间的时间。所以即使你通过立即构建 CSV 字符串来使其工作,也不会提高效率。