首页 > 解决方案 > 使用 passport-spotify 和 spotify-web-api-node 进行 API 调用的问题

问题描述

我有一个异步功能,它使用 Spotify 的授权来获取用户的顶级艺术家和曲目,然后将其放入数据库中。最近,我重组了我的数据库函数以支持异步调用,但现在我的 API 调用不再起作用。我收到一条错误消息,因为当代码到达该点时,我提供 api-call 的 accessKey 没有给出值,因此我推断问题是我的代码没有按需要播放异步性(尝试一个接一个地说这个词 10 次......)。

我对这种异步思考代码的方式非常陌生,并希望您能帮助我构建代码,以便它根据需要发挥作用。

目前,由于我上面描述的异步问题,代码在下一行停止,其中 accessToken 的值为“未定义”。

spotifyApi.setAccessToken(accessToken);

/* Function for retrieving data from spotify passport */
module.exports = function(passport) {
    passport.use(
        new SpotifyStrategy(
          {
            clientID: 'CLIENT ID',
            clientSecret: 'CLIENT SECRET',
            callbackURL: 'http://localhost:8888/auth/spotify/callback',
            passReqToCallback: true
          },
          async (accessToken, refreshToken, expires_in, profile, done) => {
            
            
            /* Put the incoming data in an object "aUser" */
            const aUser = Object.create(user);
            aUser.username = profile.username;
            aUser.displayName = profile.displayName;
            aUser.profilePicture = profile.photos[0];
            aUser.email = profile._json.email;
            
            /* RUN ALL CODE BELOW THIS IN userHandler Async function (to keep track of
              user_id throughout all coming calls). This will first check if user
              is in db, if not add it, and return it's user_id for coming calls, if
              it is in db, it will simply return it's user_id to be used in coming
              calls */
              
              async function checking() {

                /* Check if user is in DB, if not, add. Store user_id in "user" for
                using in other calls */

                let user_id = await checkUser(aUser.username, aUser.displayName, aUser.profilePicture, aUser.email);

                /* Check if artistPreferences OR trackPreferences contain row that
                was created 30 days or longer ago. If true, delete all rows
                in both tables and then run code below. If false, return from function */

                let preferencesStatus = await checkPreferences(user_id);
              
                // If user preferences was older than 30 days and checkPreferences
                // deleted the tables, run the folliwing code:
                if (preferencesStatus === true) {
                 
                    /* SET UP SPOTIFY API CALL TO GET TOP STATS FROM USER */

                    // Initialize spotifyapi object
                    var spotifyApi = new SpotifyWebApi();

                    // Set accesstoken for api objct
                    spotifyApi.setAccessToken(accessToken);
                
                    /* STEP 1: RETRIEVE TOP ARTISTS FOR CURRENT USER */

                    spotifyApi.getMyTopArtists({ limit: 1 })
                    .then(function(data) {
                        let topArtistsRaw = data.body.items;
                    
                        // Map top artists and key data into a new array
                        let mappedArtists = topArtistsRaw.map(artist => {
                            return {
                            artist: artist.name, 
                            popularity: artist.popularity,
                            url: artist.external_urls.spotify,
                            image: artist.images[0].url
                            }
                        });

                        // Map through each favorite artist of the user
                        mappedArtists.map(artist => {
                            let a_artist = artist.artist;
                            let a_popularity = artist.popularity;
                            let a_url = artist.url;
                            let a_image = artist.image;

                            // Check if artist is in the general artist-table, if not add
                            // Store the artist_id in variable
                            let artist_id = checkArtist(a_artist);
                            console.log(`artist ID NEW: ${artist_id}`);

                            // Add the artist to current users artistPreferences table
                            addArtistPreferences(user_id, artist_id);
                        });
                    });

                    /* STEP 2: RETRIEVE TOP TRACKS FOR CURRENT USER */
                    spotifyApi.getMyTopTracks({ limit:1 })
                    .then(function(data) {
                    
                        let topTracksRaw = data.body.items;

                        // Map key data for each track into new array
                        let mappedTracks = topTracksRaw.map(track => {
                            return {
                            trackname: track.name, 
                            artist: track.artists[0].name,
                            popularity: track.popularity,
                            url: track.external_urls.spotify
                            }
                        });

                        // Check if each track is in the DB, if not add
                        mappedTracks.map(track => {
                            let a_track = track.trackname;
                            let a_artist = track.artist;
                            let a_url = track.url;
                            let a_popularity = track.popularity;
                        
                            // Check if current track is in the collective artist/track DB
                            // Store track_id in variable
                            let track_id = checkTrack(a_track, a_artist);
                
                            // Add the user trackPreferences DB's
                            addTrackPreferences(user_id, track_id, a_artist);
                        });
                    });
                }   
              }  

              checking();

              return done(null, profile);
   
          }         
        )
      );

      // Serialize
      passport.serializeUser(function(user, done) {
        done(null, user);
      });
      
      passport.deserializeUser(function(user, done) {
          done(null, user);
      });
}

标签: node.jsasynchronous

解决方案


我必须做一些事情才能完成这项工作:

  1. 删除以下行:passReqToCallback: true- 激活此选项对 spotify 策略的响应类型错误,因此禁用它使其正确。

  2. 我将映射函数调整为异步格式,如下所示:

                             mappedTracks.map(async track => {
                             let a_track = track.trackname;
                             let a_artist = track.artist;
                             let a_url = track.url;
                             let a_popularity = track.popularity;
    
                             // Check if current track is in the collective artist/track DB
                             // Store track_id in variable
                             let track_id = await checkTrack(a_track, a_artist);
                             console.log('user_id and track_id: ' + user_id + ' and ' + track_id);
    
    
                         // Add the user trackPreferences DB's
                         addTrackPreferences(user_id, track_id, a_artist);
                     });
    
  3. 我还使用 await 语句更新了函数调用:await checking();


推荐阅读