【问题标题】:Need help retrieving items in multiple playlists需要帮助检索多个播放列表中的项目
【发布时间】:2019-08-27 16:33:15
【问题描述】:

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

我尝试在代码中的不同位置放置 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;
  }
}

因此,需要一些帮助,了解将循环播放列表数组的代码放置在何处。

【问题讨论】:

  • 您能在问题中添加您的尝试吗?最好在单独的代码块中,这样工作版本就不会混乱。
  • 当然,这里是:code function GatherVideos(pageToken, finished) { for (var p=0;p
  • 您将要编辑您的问题并将脚本不添加为评论。还有 build_html 函数
  • 我无法正确格式化代码...抱歉...
  • @user1106252 我通常会在我喜欢的编辑器中格式化代码。根据我的喜好,缩进 4 个空格,然后复制到问题中。

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


【解决方案1】:

您遍历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(如果页面超过 1 页),这又会再次遍历整个 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。我希望我把代码写得足够清楚,让它自己说话。如果您有任何问题,请在 cmets 中提问。

【讨论】:

  • 你太慷慨了,谢谢。你的代码让我明白我对javascript知之甚少!昨天我确实花了一些时间在看 Promises,但很难理解它。不过,您的代码中有很多我不明白的地方,尤其是如何将其集成到我已经拥有的代码中,即代码是如何被触发的?调用哪个函数以及从哪里调用?播放列表是如何传入的……等等。提前感谢您的努力。
猜你喜欢
  • 1970-01-01
  • 2014-02-05
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多