Search code examples
javascriptjqueryajaxpromisespotify

Best practice for nesting ajax calls


I am creating a simple app using Spotify REST API and JQuery where users can find an artist, and then it will show info about the artist, related artists, and most listened to songs on-page. I created 3 ajax calls which u can see below and everything works, but I think that it can be written in a better way (promises maybe?).

The first ajax call gets id from the server and create some DOM elements. The second two ajax calls need id to run and also create DOM elements. There is also a delete button that should delete DOM elements built from the data of each ajax call.

Is it possible to have it nested using the best practice or this is the only way possible?


    artistForm.submit((e) => {
    e.preventDefault();
    let inputSearchQuery = artistInput.val();
    let searchQuery = encodeURI(inputSearchQuery);

    $.ajax({
        url: `${baseUrl}search?q=${searchQuery}&type=artist`,
        type: 'GET',
        datatype: 'json',
        headers: {
            'Authorization': 'Bearer ' + accessToken
        }
    }).done((resp) => {

        
        const artistId = (resp.artists.items[0].id);
        // working with data and appending them on DOM


        $.ajax({
            url: `${baseUrl}artists/${artistId}/top-tracks?country=CZ`,
            type: 'GET',
            datatype: 'json',
            headers: {
                'Authorization': 'Bearer ' + accessToken
            }
        }).done((resp) => {

            // working with data and appending them on DOM

            $.ajax({
                url: `${baseUrl}artists/${artistId}/related-artists`,
                type: 'GET',
                datatype: 'json',
                headers: {
                    'Authorization': 'Bearer ' + accessToken
                }
            }).done((resp) => {

                // working with data and appending them on DOM

                deleteArtist.click(() => {
                   // need to have acces to data from every ajax call.

                })

            });
        });
    });
});

Solution

  • Given your work case, you could consider the following method:

    artistForm.submit(async (e) => {
        e.preventDefault();
        let inputSearchQuery = artistInput.val();
        let searchQuery = encodeURI(inputSearchQuery);
    
        let artist = await $.ajax({
            url: `${baseUrl}search?q=${searchQuery}&type=artist`,
            type: 'GET',
            datatype: 'json',
            headers: {
                'Authorization': 'Bearer ' + accessToken
            }
        });
    
        const artistId = artists.items[0].id;
        let topTracks = await $.ajax({
            url: `${baseUrl}artists/${artistId}/top-tracks?country=CZ`,
            type: 'GET',
            datatype: 'json',
            headers: {
                'Authorization': 'Bearer ' + accessToken
            }
        });
    
        let relatedArtists = await $.ajax({
            url: `${baseUrl}artists/${artistId}/related-artists`,
            type: 'GET',
            datatype: 'json',
            headers: {
                'Authorization': 'Bearer ' + accessToken
            }
        });
    
        deleteArtist.click(() => {
            // need to have access to data from every ajax call.
        });
    });
    

    This is assuming you are using jQuery 3.0 or higher. If not you can find a nice wrapper function here.

    If you want to learn more about promises and async await I recommend the following video's: JavaScript Promises In 10 Minutes - by Web Dev Simplified and The Async Await Episode I Promised - by Fireship.