JavaScript Youtube Data API – Pagination

Im new to JavaScript and programming anything other than a basic programs in general. I figure that building something is a good way to learn.

At the moment I’m trying to use the Youtube Data API. What I want to do is use OAuth to pull a list of subscriptions from any Youtube account that’s authorized and save it in an array. I followed the JavaScript Quickstart on the Google Developers website. That was easy enough to do. I added code that stores key/value pairs from ‘title’ into an array called ‘allSubs’

<script>
  /**
   * Sample JavaScript code for youtube.subscriptions.list
   * See instructions for running APIs Explorer code samples locally:
   * https://developers.google.com/explorer-help/code-samples#javascript
   */

  allSubs = [];

  function authenticate() {
    return gapi.auth2.getAuthInstance()
        .signIn({scope: "https://www.googleapis.com/auth/youtube.readonly"})
        .then(function() { console.log("Sign-in successful"); },
              function(err) { console.error("Error signing in", err); });
  }
  function loadClient() {
    gapi.client.setApiKey("API_KEY");
    return gapi.client.load("https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest")
        .then(function() { console.log("GAPI client loaded for API"); },
              function(err) { console.error("Error loading GAPI client for API", err); });
  }
  // Make sure the client is loaded and sign-in is complete before calling this method.
  function execute() {
    return gapi.client.youtube.subscriptions.list({
      "part": [
        "snippet,contentDetails"
      ],
      "maxResults": 50,
      "mine": true,
      "order": "alphabetical"
    })
        .then(function(response) {
                // Handle the results here (response.result has the parsed body).
                items = response.result.items;
                itemsLength = items.length;

                for  (i=0; i<itemsLength; i++){
                  x = response.result.items[i].snippet.title;
                  allSubs.push(x);
                }


                console.log(allSubs);
              },
              function(err) { console.error("Execute error", err); });
  }
  gapi.load("client:auth2", function() {
    gapi.auth2.init({client_id: "CLIENT_ID"});
  });
</script>
<button onclick="authenticate().then(loadClient)">authorize and load</button>
<button onclick="execute()">execute</button>

The issue I ran into is pagination. The limit on ‘maxResults’ is 50. If you subscribe to more than 50 channels, the code won’t pick them up. I have to use ‘nextPageToken’ to loop through as many times as needed to get the full list.
I read the Google Developer ‘Implementation: Pagination’ page but I didn’t find it helpful. I then read many forums (including this one) and watched many videos that covered the topic. The closest I have gotten is the following code:

<script>
  /**
   * Sample JavaScript code for youtube.subscriptions.list
   * See instructions for running APIs Explorer code samples locally:
   * https://developers.google.com/explorer-help/code-samples#javascript
   */

  var allSubs = [];


  function authenticate() {
    return gapi.auth2.getAuthInstance()
        .signIn({scope: "https://www.googleapis.com/auth/youtube.readonly"})
        .then(function() { console.log("Sign-in successful"); },
              function(err) { console.error("Error signing in", err); });
  }
  function loadClient() {
    gapi.client.setApiKey("API_KEY");
    return gapi.client.load("https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest")
        .then(function() { console.log("GAPI client loaded for API"); },
              function(err) { console.error("Error loading GAPI client for API", err); });
  }
  // Make sure the client is loaded and sign-in is complete before calling this method.
  function execute(pageToken, finished) {

      request = gapi.client.youtube.subscriptions.list({
        "part": [
          "snippet,contentDetails"
        ],
        "maxResults": 50,
        "mine": true,
        "order": "alphabetical",
        pageToken: pageToken
      });

      request.execute(function(response) {
        items = response.result.items;
        itemsLength = items.length;

        for  (i=0; i<itemsLength; i++){
          x = response.result.items[i].snippet.title;
          //y = response.result.items[i].snippet.resourceId.channelId;
          //z = [x,y];
          allSubs.push(x);
        }
        if (!response.nextPageToken)
            finished();
        else
            execute(response.nextPageToken, finished);
      });

      console.log(allSubs);
  }


  gapi.load("client:auth2", function() {
    gapi.auth2.init({client_id: "CLIENT_ID"});
  });


</script>
<button onclick="authenticate().then(loadClient)">authorize and load</button>
<button onclick="execute()">execute</button>

The good news is I have a complete list now.
But now I have two new problems.

  1. On top of giving me the array I wanted I also have a number of other arrays that are subsets of the main array in 50 intervals. I want a single array. I’m clearly messing up the loop somehow. Maybe the scope is incorrect but I haven’t been able to figure it out; and

  2. I get an error that says ‘example.html:48 Uncaught TypeError: finished is not a function’. Makes sense since I had never defined ‘finished()’. But the code doesn’t seem to work if I don’t include this function. I have no idea why.

Any help would be greatly appreciated, either about this specific problem or about program problem solving generally. There’s probably an easy solution that I’m oblivious to. Again Im a beginner and am probably making some dumb mistakes here. But I figure failing is a good way to learn.