Steve
Steve

Reputation: 51

How to execute a function only after a request.execute to gapi.client.youtube has completed?

I am trying to get results from multiple pages of a youtube playlist. The problem is that I cannot get my second request (for the second page) to execute only after I have received the data from the first one. I've tried promises, deferrals, callbacks, and nothing seems to work.

function requestVideoPlaylist(playlistId, pageToken, pages) {
  $('#video-container').html('');
  var requestOptions = {
    playlistId: playlistId,
    part: 'snippet',
    maxResults: 10
  };
  if (typeof(pages)==='undefined') {
    pages = 2;
  }

  var i = 0
  while (i++ < pages){
    var request = gapi.client.youtube.playlistItems.list(requestOptions);
    request.execute(function(response) {

      nextPageToken = response.result.nextPageToken;

      var playlistItems = response.result.items;    
      console.log(playlistItems)

      if (playlistItems) {
        $.each(playlistItems, function(index, item) {
          displayResult(item.snippet);
        });
      } else {
        $('#video-container').html('Sorry you have no uploaded videos');
      }
    }).done(console.log('test'));

    if (nextPageToken) {
      console.log(nextPageToken)
      requestOptions.pageToken = nextPageToken;
    }
  }       
}

In this example I get a message 'Uncaught TypeError: Cannot read property 'done' of undefined' for the .done(console.log('test)) and nothing from console.log(nextPageToken), as that part also executes before the response is received.

Upvotes: 2

Views: 1844

Answers (1)

F&#233;lix Saparelli
F&#233;lix Saparelli

Reputation: 8749

Obviously request.execute() does not return anything (undefined), much less a Promise, so stick your function call directly into the callback, like this:

request.execute(function(response) {
  nextPageToken = response.result.nextPageToken;

  var playlistItems = response.result.items;    
  console.log(playlistItems);

  if (playlistItems) {
    $.each(playlistItems, function(index, item) {
      displayResult(item.snippet);
    });

    loadNextPage(nextPageToken); // <--
  } else {
    $('#video-container').html('Sorry, you have no uploaded videos');
  }
});

As an aside, you cannot do .done(console.log(...)), as that is equivalent to:

var foo = console.log(...);
getAPromise().done(foo);

and foo is whatever console.log() returns, which in this case is undefined, so you're calling .done(undefined) which obviously won't do what you mean. Instead, you need to do something like what guest271314 suggested:

getAPromise().done(function(arg) {
  console.log(arg);
});

(As an aside to that, I suggest you go read a JS book to strengthen your understanding of typical patterns such as this.)

Upvotes: 1

Related Questions