0

I am trying to create a serverless React app to make recommendations by processing some data from Spotify's API. I am using spotify web api js as a wrapper to make the API calls. My problem is that one of the results I get from my functions appears when I call console.log on it, but not when I pass it to another function. Here's the code for the submit handler on my page:

handleSubmit(e) {        
        e.preventDefault();
        this.setState({recOutput: {}});
        spotify.setAccessToken(this.props.vars.token);
        spotify.searchArtists(this.state.artist)
            .then(res => this.getRecs(res))
            .then(output => this.processResults(output))
            .then(processed => this.setState({resultReceived: true, recOutput: processed}))
            .catch(err => this.handleError(err));
        
    }
And here are all the functions it's calling:

/**
     * Gets recommendations for a specific artist and outputs recOutput value in redux store
     * @param {string} name The name of the artist
     * @return Promise with output
     * TODO: catch errors again lol
     * /
    **/
    async getRecs(name) {
        const MAX_SONGS = 50;
        var output = {};
        spotify.searchPlaylists(name, {limit: 1})
        .then(searchTotal => {spotify.searchPlaylists(name, {limit: 50, offset: Math.floor(Math.random() * (searchTotal.playlists.total/50))}).then(
            res => {
                

                for (let i of res.playlists.items) {
                        spotify.getPlaylistTracks(i.id).then(
                            pt => {
                                let curSongs = 0;
                                if (pt == undefined) {
                                    return;
                                }
                                for (let track of pt.items) {
                                    if (curSongs > MAX_SONGS) break;
                                    if (track.track != null 
                                        && track.track.artists[0].name !== name
                                        && track.track.artists[0].name !== "") {
                                        if (track.track.artists[0].name in output) {
                                            output[track.track.artists[0].name]++;
                                        } else {
                                            output[track.track.artists[0].name] = 1;
                                        }
                                    }
                                    curSongs++;
                                }
                
                            })
                    }
                
            }
        )
    }).catch(err => this.handleError(err));
        
        return output;
    }
    
    
    
        /**
     * Processes results from our query to spotify, removing entries beyond a certain threshhold then sorting the object.
     * @return Promise for updated results update
     */
    async processResults(input) {
        debugger;
        let processed = {};
        for (let key in input)   {
            console.log(key);
            if (input[key]> 10) {
                processed.key = input.key;
            }
        }
        return processed;
    }

My problem is that when I call .then(output => this.processResults(output)), the process method receives an empty output in the debugger, but when I call .then(output => console.log(output)), I see the expected output for the function.

Here is the context of my component: Component context

rudiejd
  • 392
  • 2
  • 13
  • Did you check that `this` is the scope of `processResults()`? – DadiBit Oct 06 '20 at 18:33
  • @DadiBit yup i did console.log(this) inside of the output function and made sure the context was correct. I actually forgot to bind my new functions, but that didn't make a difference - calling the functions was working anyway, processResults just gets an empty object for some reason. – rudiejd Oct 06 '20 at 18:39
  • @DadiBit added the context to the post – rudiejd Oct 06 '20 at 18:43
  • Beware of relying on `console.log` to display async data: the console's output can be updated after-the-fact to reflect the *current* reference value, meaning by the time you look at the log, other code may have executed. – Dave Newton Oct 06 '20 at 18:46
  • 2
    `getRecs` confuses me a little; I see a `return output`, but that'd be returned before the processing actually happens, since `output` is *populated* asynchronously. Which leads back to my previous comment. – Dave Newton Oct 06 '20 at 18:49
  • @DaveNewton i was thinking return output would give me a promise that terminates after output is populated, meaning that processRecs should wait for the getRecs to be done populating first. How would I write it like that? – rudiejd Oct 06 '20 at 18:56
  • Same way as any other async call, e.g., [How do I return the response from an aynchronous call](https://stackoverflow.com/q/14220321/438992). – Dave Newton Oct 06 '20 at 19:01
  • @J.D.Rudie if it works, then let DaveNewton please answer and mark the question as solved. – DadiBit Oct 06 '20 at 19:14
  • @DaveNewton it looks like even when I change the processResults function to do "await input" and call it in the body of the getRecs function, I still get an empty object. Not really sure how to fix this – rudiejd Oct 06 '20 at 19:30
  • I'm not sure what you tried; the issue is that you're not waiting for `getRecs`. – Dave Newton Oct 06 '20 at 19:32
  • @DaveNewton wouldn't doing await in the body of processResults do that since I'm just passing it a promise? That's what I tried – rudiejd Oct 06 '20 at 19:33
  • `getRecs` returns an empty object, not a promise. – Dave Newton Oct 06 '20 at 19:35
  • @DaveNewton so i guess my main question is how can i wait on getRecs to finish populating that object? should i be doing this inside of one of the callbacks? sorry i'm so daft, this is just my first time doing stuff with react – rudiejd Oct 06 '20 at 19:43

0 Answers0