Strange issue when recursively concatenating to string

51 views Asked by At

I have a JavaScript function which recursively calls the Spotify API in order to get data for a users saved songs such as track name, album, date added etc. (call limit is 50 so I need to repeat the call many times). It then manipulates the data into .csv format for the user to download. It is shown below (it works completely fine).

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);

I tried to increase the efficiency by having the called data be turned into .csv format straight away and concatenating to a string (code below):

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");

For an unknown reason to me this code only returns the .csv string from the first api call (not the total string which is combined with all of the subsequent ones).

I've tried bugfixing by using console.log on certain parts and the code correctly appends to the csv as each new call is passed. However, after the final call all hell breaks loose and the console instantly returns all of the logs that happened as each subsequent call happened (with the csv string growing in size), but somehow in REVERSE order. Does anyone have any ideas? Thanks.

1

There are 1 answers

0
trincot On

The reason that the second version does not collect all the results, is that now you don't mutate the structure in which you collect the result (like you did with tracksArray.push()), but assign to a local variable (csv +=). The latter creates a new string and doesn't mutate anything. You can never achieve that the recursive call would change the content of the callers csv string; strings are immutable: there is no way to make a function that changes the string you pass to it.

But as already mentioned in comments, this effort to increase efficiency is not tackling the bottleneck. The bottleneck is the request/response delay -- the time between a client request and the reception of the server's response. So even if you make it work by immediately building the CSV string, it will not improve the efficiency.