Experiencing undefined values when retrieving data from music API arrays

I’m developing a JavaScript application that interfaces with a music API to showcase the most popular albums from various artists. The function involves entering an artist’s name which retrieves their ID, allowing me to access all their albums. I then want to compile the relevant details into a 2D array and filter it to display only the top 5 albums ranked by popularity.

Here is the code snippet I’m currently using:

var albumData = [];
var processedCount = 0;
var totalItems = 0;

$(document).ready(function () {
    $("#findButton").click(function () {
        findArtist();
    });

    function findArtist() {
        var artistName = document.getElementById('inputField').value;
        $.get("https://api.spotify.com/v1/search?q=" + artistName + "&type=artist", function (response) {
            fetchAlbumList(response.artists.items[0].id);
        });
    }

    function fetchAlbumList(id) {
        $.getJSON("https://api.spotify.com/v1/artists/" + id + "/albums?album_type=album",
        function (data) {
            totalItems = data.items.length;
            for (var j = 0; j < data.items.length; j++) {
                buildDataArray(data.items[j].href);
            }
        });
    }

    function displayTopAlbums(sortedData) {
        var tableRow = $('<tr/>');
        for (var k = 0; k < 5; k++) {
            tableRow.append("<td>" + sortedData[k][0] + "</td>"); // Title
            tableRow.append("<td>" + sortedData[k][1] + "</td>"); // Artist
            tableRow.append("<td>" + sortedData[k][2] + "</td>"); // Date
            tableRow.append("<td>" + sortedData[k][3] + "</td>"); // Track Count
            tableRow.append("<td>" + sortedData[k][4] + "</td>"); // Rating
        }
        $('table').append(tableRow);
    }

    function buildDataArray(albumUrl) {
        $.getJSON(albumUrl, function (albumInfo) {
            if (albumData.length <= processedCount) {
                albumData.push([]);
            }
            albumData[processedCount].push(albumInfo.name);
            albumData[processedCount].push(albumInfo.artists[0].name);
            albumData[processedCount].push(albumInfo.release_date);
            albumData[processedCount].push(albumInfo.tracks.total);
            albumData[processedCount].push(albumInfo.popularity);
            processedCount++;
            checkComplete(--totalItems);
        });
    }

    function compareByRating(first, second) {
        if (first[4] === second[4]) {
            return 0;
        } else {
            return (first[4] > second[4]) ? -1 : 1;
        }
    }

    function checkComplete(remaining) {
        if (remaining <= 0) {
            albumData.sort(compareByRating);
            displayTopAlbums(albumData);
        }
    }
});

I’m encountering undefined errors when accessing elements in the array. This occurs both when adding data to the array and when attempting to read from it for display. I’m considering that it might be a problem with how I initialize the array or manage asynchronous calls, but I’m not sure where the problem lies.

The problem is related to how you’re initializing the albumData array in the buildDataArray function. The check if (albumData.length <= processedCount) could lead to issues due to asynchronous requests completing in parallel. This may cause attempts to read or write to the same index before it’s properly set up. Instead, you should initialize the nested arrays for albumData in the fetchAlbumList function before processing the album items. Modify it as shown:

function fetchAlbumList(id) {
    $.getJSON("https://api.spotify.com/v1/artists/" + id + "/albums?album_type=album",
    function (data) {
        totalItems = data.items.length;
        // Initialize all arrays upfront
        albumData = new Array(totalItems);
        for (var j = 0; j < data.items.length; j++) {
            buildDataArray(data.items[j].href, j); // pass index
        }
    });
}

Also, adjust the buildDataArray function to take an index parameter so that you can directly assign values to albumData[index], which avoids race conditions while processing the data.