Kennos
Kennos

Reputation: 237

Struggling with asynchronous code and promises

I am creating a web player by using the spotify SDK. While doing so, everytime I click any play button in the player I want to execute the sdk function: player.getCurrentState() to fetch the new album art, trackname and artistname of the currently playing track. Upon receiving result I want the current element in the HTML structure to change accordingly. However, if pressed at first the song is played normally but the error message is shown, but when pressed a second time the elements are changed accordingly. After that, when I keep switching between different tracks, the changes always lag one click behind. I expect it to be due to asynchronous code but I can't get the hang of this asynchronousness in javascript.

document.getElementById("playbtn").addEventListener("click", function () {
           const play = ({spotify_uri, playerInstance: {_options: {getOAuthToken, id}}}) => {
                getOAuthToken(access_token => {
                    fetch(`https://api.spotify.com/v1/me/player/play?device_id=${id}`, {
                        method: 'PUT',
                        body: JSON.stringify({uris: [spotify_uri]}),
                        headers: {
                            'Content-Type': 'application/json', 'Authorization': `Bearer ${access_token}`
                        },
                    });
                });
            };
            play({
                playerInstance: player,
                spotify_uri: 'spotify:track:14iN3o8ptQ8cFVZTEmyQRV',
            });
            update();
}, false);


function update(){
        player.getCurrentState().then(state => {
            if (!state) {
                console.error('User is not playing music through the Web Playback SDK');
                return;
            }
            document.getElementById("album").src = state.track_window.current_track.album['images'][2]["url"];
            document.getElementById("trackname").innerHTML = state.track_window.current_track['name'];
            document.getElementById("artistname").innerHTML = state.track_window.current_track['artists'][0]['name'];
        });
}

I also tried the functions async and await but this gives the same result. Help is appreciated!

Spotify documentation: https://developer.spotify.com/documentation/web-playback-sdk/reference/#api-spotify-player-getcurrentstate

Im also thinking the same kind of asynchronous problems are appearing in a previous question I asked: Doesn't add records into PouchDB when used same function over again

Upvotes: 1

Views: 237

Answers (1)

darklightcode
darklightcode

Reputation: 2772

Your problem for one click behind is because the new song was not loaded, nor the player updated. In the demo below i added player.addListener('player_state_changed', update); in the main function so the event will trigger your update method.

var player = null;

function update(changedStateEvent) {
  console.log(changedStateEvent);
  player.getCurrentState().then(state => {
    if (!state) {
      console.error('User is not playing music through the Web Playback SDK');
      return;
    }
    document.getElementById("album").src = state.track_window.current_track.album['images'][2]["url"];
    document.getElementById("trackname").innerHTML = state.track_window.current_track['name'];
    document.getElementById("artistname").innerHTML = state.track_window.current_track['artists'][0]['name'];
  });
}

const play = ({
  spotify_uri,
  playerInstance: {
    _options: {
      getOAuthToken,
      id
    }
  }
}) => {
  getOAuthToken(access_token => {
    fetch(`https://api.spotify.com/v1/me/player/play?device_id=${id}`, {
      method: 'PUT',
      body: JSON.stringify({
        uris: [spotify_uri]
      }),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${access_token}`
      },
    });
  });
};
window.onSpotifyWebPlaybackSDKReady = () => {
  // You can now initialize Spotify.Player and use the SDK
  player = new Spotify.Player({
    name: 'Carly Rae Jepsen Player',
    getOAuthToken: callback => {
      // Run code to get a fresh access token

      callback('access token here');
    },
    volume: 0.5
  });

  // use events
  // https://developer.spotify.com/documentation/web-playback-sdk/reference/#event-player-state-changed
  player.addListener('player_state_changed', update);

}

document.getElementById("playbtn").addEventListener("click", function() {

  play({
    playerInstance: player,
    spotify_uri: 'spotify:track:14iN3o8ptQ8cFVZTEmyQRV',
  });

}, false);

Upvotes: 3

Related Questions