需要帮助来检索多个播放列表中的项目

时间:2019-04-05 17:57:58

标签: javascript youtube-api youtube-data-api

得到一些效果很好的代码,它将检索指定播放列表中的所有项目,但需要对其进行修改,以便它可以遍历播放列表数组并检索每个列表中的所有项目。

我曾尝试在代码的不同位置放置for-next循环,但是由于我的JavaScript很差,所以这些努力都失败了,我不知道下一步该怎么做。

function onGoogleLoad() {
  showhide('hidden');
  getSearchParameters();
  gapi.client.setApiKey(APIKEY);
  gapi.client.load('youtube', 'v3', function () {

    GatherVideos("", function () {
      for (var i = 0; i < allVideos.length; i++) {
        console.log(allVideos[i].snippet.title + " published at " + allVideos[i].snippet.publishedAt)
      }

      showhide('visible');
      build_html(allVideos);
    });

  });
}
ORIGINAL CODE ...


        function GatherVideos(pageToken, finished) {
            var request = gapi.client.youtube.playlistItems.list({
                part: 'snippet, contentDetails',
                playlistId: 'UU_FksrzP3q-IuoWTiG501LQ',
                maxResults: 50,
                pageToken: pageToken
            });

            request.execute(function(response) {
                allVideos = allVideos.concat(response.items);
                if (!response.nextPageToken)
                    finished();
                else
                    GatherVideos(response.nextPageToken, finished);
            });
        }
END ORIGINAL CODE

NEW CODE WITH ATTEMPT AT LOOPING ...

        function GatherVideos(pageToken, finished) {
                for (var p=0;p<allPlaylists.length;p++)
                {
                    console.log('Gathering: ' + allPlaylists[p]);
                var request = gapi.client.youtube.playlistItems.list({
                 part: 'snippet, contentDetails',
                  playlistId: allPlaylists[p],
                   maxResults: 50,
                    pageToken: pageToken
                });             

                request.execute(function(response) {
                        console.log('Executing: ' + request);               
                   allVideos = allVideos.concat(response.items);
                    if (!response.nextPageToken)
                       finished();
                   else
                    GatherVideos(response.nextPageToken, finished);
                    });
           } //End for loop
        }
END NEW CODE ...

  function build_html(parArray) {
    var n = 0;
    var playlistHtml = '';
    var rows = Math.floor(parArray.length / vinrow);
    var rem = (allVideos.length % vinrow);
    if (rem > 0) {
      rows++;
    }

    for (var i = 0; i < rows; i++) {
      playlistHtml += '<div class="row">';

      for (var k = 0; k < vinrow; k++) {
        if (n < parArray.length) {
          playlistHtml += '<div id=' + n + ' class="col item"><img class="img-responsive fit-image" src="' + 
            parArray[n].snippet.thumbnails.default.url + '"><div class="vtitle">' + 
            parArray[n].snippet.title + '</div></div>';

          n++;
        } else {
          playlistHtml += '<div class="col item"><div class="vtitle"> </div></div>';
        }
      }

      playlistHtml += "</div>";
    }

    playlist_div.innerHTML = playlistHtml;
  }
}

因此,需要一些有关将代码放置在播放列表数组中的位置的帮助。

1 个答案:

答案 0 :(得分:0)

您遍历allPlaylists,建立请求并将其保存在request变量中。问题是,每次执行循环都会覆盖request变量。以后调用request.execute(...)时,您仅执行最后一个请求构建(数组中的最后一个播放列表)。

您应将请求执行移至 for 循环内。

for (var p = 0; p < allPlaylists.length; p++)
{
    console.log('Gathering: ' + allPlaylists[p]);
    var request = gapi.client.youtube.playlistItems.list({ /* ... */ });
    request.execute(/* ... */);
}

以上内容已解决了部分问题。 但是,这不能完全解决问题。。您递归地调用GatherVideos(如果页面多于一页),依次遍历整个allPlaylists再次排列。为每个播放列表设置新的请求。

要解决上述问题,应从单个播放列表中检索视频,并将其移至其自己的方法中。由于不同的原因,使用当前结构有点麻烦,因此我已经使用某种不同的方法从头开始对其进行了重建。这可能不是您要找的确切答案,但我希望它会给您一些启发:

async function listPlaylist(options = {}) {
    var maxResults, pendingMaxResults, response;

    options = Object.assign({}, options);
    maxResults = options.maxResults;

    if (Number.isInteger(maxResults) && maxResults > 0) {
        // set options.maxResults to a value 1-50
        options.maxResults = (maxResults - 1) % 50 + 1;
        pendingMaxResults = maxResults - options.maxResults;
    } else if (maxResults === "all") {
        pendingMaxResults = "all";
    }

    response = await Promise.resolve(gapi.client.youtube.list(options));

    if (response.nextPageToken && (pendingMaxResults === "all" || pendingMaxResults > 0)) {
        options.maxResults = pendingMaxResults;
        options.pageToken = response.nextPageToken;
        return response.items.concat(await listPlaylist(options));
    } else {
        return response.items;
    }
}

(async function () {
    var playlistsVideos, videos;

    // retrieve all videos of all playlists
    playlistsVideos = await Promise.all(allPlaylists.map(function (playlistId) {
        return listPlaylist({ 
            id: playlistId,
            part: "snippet, contentDetails",
            maxResults: "all"
        });
    }));

    // the above variable `playlistsVideos` is in the format:
    // [[p1v1, p1v2, p1v3], [p2v1, p2v2, p2v3]] (p = playlist, v = video)
    // this needs to be flattened to have the result you want
    videos = playlistsVideos.reduce((videos, playlistVideos) => videos.concat(playlistVideos), []);
})();

我建议您查阅指南Using Promises并查阅async/await的文档。以上内容基于YouTube API V3。我希望我编写的代码足够清晰,足以说明一切。如果您有任何疑问,请在评论中提问。