Jammming Feature Request - Multiple Playlists and problems with Promises

Hello all,

This is my first post in these forums so please forgive any errors and I hope you can help.

I’ve been working on implementing the Multiple Playlists for the feature request as part of the Jammming project. The first step is to retrieve and display the playlists and I am asked to:

" To retrieve the user ID, we will hit the https://api.spotify.com/v1/me endpoint, as we currently do in Spotify.savePlaylist(). We will refactor this request to a new method called Spotify.getCurrentUserId() (to avoid duplicate code). At the top of Spotify.js, we will instantiate a variable called userId with no value. Then inside Spotify.getCurrentUserId(), we will check to see if userId’s value is already set (from a previous call to the function). If it is, we will create and return a promise that will resolve to that value. Otherwise we will make the call to the /me endpoint and return that request’s promise."

So as I understand it, I need to refactor the userId request in savePlaylist() into a new method called .getCurentUserId(). This new method will check if the variable userId has a value assigned, if yes then I need to create a promise (this stumps me) which will resolve to the value of userId. Else I need to make a fetch call to the /me endpoint. I have created the following:

savePlaylist(playlistName, trackUris) {
        //checks if playlistName or arr have a value, if not it will return.
            if (!playlistName || !trackUris.length) {
                return;
            }
            //stores user access token
            const accessToken = Spotify.getAccessToken();
            //stores the authorisation for the implicit grant flow
            const headers = {
                Authorization: `Bearer ${accessToken}`
            };
            
            let getUserId = Spotify.getCurrentUserId();
            console.log(getUserId); //retrieve userId
            getUserId.then(() => { return fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, //once userId has been called then make the call to /playlists endpoint
                                                        {
                                                            headers: headers,
                                                            method: 'POST',
                                                            body: JSON.stringify({name: playlistName})
                                                                }).then(response => {
                                                                    if(response.ok){
                                                                        return response.json();
                                                                            } else {
                                                                                console.log('API has failed');
                                                                                    }
                                                                                }).then(jsonResponse => {
                                                                                        const playlistId = jsonResponse.id;
                                                                                            return fetch(`https://api.spotify.com/v1/playlists/${playlistId}/tracks`, 
                                                                                                { headers: headers,
                                                                                                  method: 'POST',
                                                                                                  body : JSON.stringify({uris: trackUris})
                                                                                                })
                                                                                            })
                                                                                        }).catch(console.log(userId))}, //catch any errors
    getCurrentUserId() {
        const accessToken = Spotify.getAccessToken();
        const headers = {
            Authorization: `Bearer ${accessToken}`
        };
        
        if(userId){ //check if userId has a value
            let promise = new Promise((resolve) => { //create a promise which resolves to userId value
                resolve(userId);
            })
            promise.then(()=>{return userId});
            console.log(userId);
        } 
        else { //otherwise make a call to the /me endpoint to grab userId
            return fetch('https://api.spotify.com/v1/me', { headers: headers }
            ).then(
                response => {
                if(response.ok){
                    return response.json(); //converts the response to json
                        } else {
                           console.log('API has failed');
                                } 
                                   }
                                        ).then(
                                            jsonResponse => {
                                                userId = jsonResponse.id;
            })
        }
    }
}

I am getting a number of errors:
App.js:77 Uncaught TypeError: Cannot read property ‘then’ of undefined
and
react-dom.development.js:4091 Uncaught TypeError: Cannot read property ‘then’ of undefined

I believe these errors are because getCurrentUserId() is not doing its job in one way or another. I am not sure I have fully understood how to implement Promises in my code correctly, nor do I believe I have refactored getCurrentUserId() into savePlaylist() correctly.

Apologies for the long post, any suggestions/criticisms/help would be appreciated.

Thanks,
Chris

Hello, and welcome to the forums!

It doesn’t look like your getCurrentUserId() method returns anything if userId has a value.

If userId doesn’t have a value, you’re returning the results of your fetch() chain, which is already a Promise. If it does have a value, you’re doing some things with Promises, but you never return anything back to whatever called getCurrentUserId()

This is one of those times when I’m not sure how much I should say because what I mentioned above might be enough of a push in the right direction for you to be off to the races again, so please let us know.

Thank you for the help! Apologies I’ve taken a while to reply, I spent the weekend away from the computer at the behest of my other half.

My getCurrentUserId() now returns a value thanks to your nudge. I’m now left with:

TypeError: Cannot read property ‘then’ of undefined

within my App.savePlaylist():

savePlaylist() {
  const trackUris = this.state.playlistTracks.map(track => track.uri);
  Spotify.savePlaylist(this.state.playlistName, trackUris).then(() => {
    this.setState({
      playlistName: 'New Playlist',
      playlistTracks: []
    })
  })
}

After some googling it seems that this error appears when a promise is undefined, which suggests to me that Spotify.savePlaylist() is not working as intended.

No worries at all. It’s good to get away sometimes.

Your Spotify.savePlaylist() method isn’t returning anything either. When you adapted it to handle multiple playlists, the original return was nested deeper into the chain of Promises and the method no longer returns anything. I catch myself doing that sometimes too

Thank you! I’ve been staring at savePlaylist() since about 10am this morning and it’s finally working. I scared the cat when I cheered.

1 Like