简体   繁体   中英

JavaScript - Spotify API, fetching playlist tracks

I am using spotify api to search for the playlists and then display them in my mobile application. I am using Ajax to get the information from the api which works fine yet I can't seem to be able to populate the div with the results and make it possible for the application to play music snippets as it doesn't want to allow event listeners. You won't be able to see all the variables used but everything before this code works perfectly fine.

var audioObject = null;
//Spotify page
$(document).on('pagecreate', '#spotify', function(){
console.log("Spotify");
$('#search').on('click', function() {
    //e.preventDefault();
    searchstring = cweather;

    if (!searchstring){
        console.log('no input');
        return;
    }
    console.log(searchstring);
    searchPlaylist(searchstring);
});

});

var userId;

var searchPlaylist = function () {
$.ajax({
    url: 'https://api.spotify.com/v1/search',
    headers: {
        Authorization: 'Bearer ' + spotifyAccessToken,
    },
    data: {
        q: searchstring,
        type: 'playlist',
        market: 'GB',
        offset: '0',
        limit: '5',
    },
    success: function (response) {
        console.log(response);

        var items = response.playlists.items;
        var resultsintohtml = '';

        $.each(items, function(index) {
            var id = items[index].id;
            var name = items[index].name;
            //var image = items[index].image[1].url;
            userId = items[index].owner.id;
            console.log(id, name, userId);
            resultsintohtml += '<div style="backgroundColor="red"" data-album-id="' + id + '" class="cover"></div>';
        });

        console.log(resultsintohtml);
        document.getElementById("results").innerHTML = resultsintohtml;

        addclickevents();
    }
});
};

var fetchTracks = function (playlistsId, userId, callback) {
$.ajax({
    url: 'https://api.spotify.com/v1/users/' + userId + '/playlists/' + playlistsId,
    headers: {
        Authorization: 'Bearer ' + spotifyAccessToken,
    },
    success: function (response) {
        console.log(response);
        callback(response);
    }
});
};

var addclickevents = function () {
$('.cover').click(function (e){
    console.log('get song');
    var target = $(this);

    if (target.hasClass('playing')) {
        audioObject.pause();
    } else {
        if (audioObject){
            audioObject.pause();
        }

        fetchTracks(target.data('playlist-id'), function (data) {
            audioObject = new
            Audio(data.tracks.items[0].preview_url);
            audioObject.play();
            target.addClass('playing');             
        });
        audioObject.addEventListener('pause', function(){
            target.removeClass('playing');
        });
    }
});
};

As this code is used I get following errors: Errors I have tried renaming the variables yet I get the very same error. I have double checked if there is any missing information from the spotify yet I am using all the available ID's already. Thanks in advance.

Update: looking closer to your code, I just noticed fetchTracks expects 3 parameters and you're passing only 2. The second parameter should be userId and the third should be the callback. I don't have a clue what your userId is, but, assuming it's 123 you should run the function like this:

...
fetchTracks(target.data('playlist-id'), "123", function (data) {
  audioObject = new Audio(data.tracks.items[0].preview_url);
  audioObject.play();
  target.addClass('playing');             
  audioObject.addEventListener('pause', function(){
    target.removeClass('playing');
  });
});
...

Considering, your code is, most likely, calling a broken URL from Spotify's point of view (which should show up as an error in your console - most likely, a 404 but possibly also 403 or 422 ).


Initial answer:

Assuming the code above is what's generating the error, at line 87 (in the above snippet), you're trying to add an event listener on audioObject . According to the error, audioObject is not a DOM element, but null . So you might want to check if the element supports the method before applying it:

...
if (audioObject)
   audioObject.addEventListener('pause', function(){
     target.removeClass('playing');
   });

or...

if (audioObject instanceof Element)
   audioObject.addEventListener('pause', function(){
     target.removeClass('playing');
   });

Note (as future reference): whenever you decide to post images of code instead of the code itself on [SO], expect being down-voted.

Another note : the above does not fix the logic of your application, which is clearly broken (or at least not working as intended). It just avoids executing the code when it would generate an error.


You probably want add the event listener inside fetchTracks() :

...
fetchTracks(target.data('playlist-id'), function (data) {
  audioObject = new Audio(data.tracks.items[0].preview_url);
  audioObject.play();
  target.addClass('playing');             
  audioObject.addEventListener('pause', function(){
    target.removeClass('playing');
  });
});
...

..., but, without a minimal working example I can't be sure.

If audioObject is only assigned a value in the callback of fetchTracks , it won't be defined when audioObject.addEventListener is called.

When you click on a .cover , the event listener is called. If the cover does not have the "playing" class, then:

  • the audioObject is still null
  • fetchTracks will be called but the callback will not fire until the response is received
  • audioObject.addEventListener will be called but the audioObject is null
  • the response for fetchTracks come back, and in the callback you set audioObject to be an instance of Audio

Is there any reason why you chose to add the event listener outside of the callback?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM