javascriptnode.jspaginationpromisebluebird

Retrieve paginated data recursively using promises


I'm using a function which returns data in a paginated form. So it'll return max 100 items and a key to retrieve the next 100 items. I want to retrieve all the items available.

How do I recursively achieve this? Is recursion a good choice here? Can I do it any other way without recursion?

I'm using Bluebird 3x as the promises library.

Here is a snippet of what I'm trying to achieve:

getEndpoints(null, platformApplication)
  .then(function(allEndpoints) {
    // process on allEndpoints
  });


function getEndpoints(nextToken, platformApplication) {
  var params = {
    PlatformApplicationArn: platformApplication
  };

  if (nextToken) {
    params.NextToken = nextToken;
  }

  return sns.listEndpointsByPlatformApplicationAsync(params)
    .then(function(data) {
      if (data.NextToken) {
        // There is more data available that I want to retrieve.
        // But the problem here is that getEndpoints return a promise
        // and not the array. How do I chain this here so that 
        // in the end I get an array of all the endpoints concatenated.
        var moreEndpoints = getEndpoints(data.NextToken, platformApplication);
        moreEndpoints.push.apply(data.Endpoints, moreEndpoints);
      }

      return data.Endpoints;
    });
}

But the problem is that if there is more data to be retrieved (see if (data.NextToken) { ... }), how do I chain the promises up so that in the end I get the list of all endpoints etc.


Solution

  • Recursion is probably the easiest way to get all the endpoints.

    function getAllEndpoints(platformApplication) {
        return getEndpoints(null, platformApplication);
    }
    
    function getEndpoints(nextToken, platformApplication, endpoints = []) {
      var params = {
        PlatformApplicationArn: platformApplication
      };
    
      if (nextToken) {
        params.NextToken = nextToken;
      }
    
      return sns.listEndpointsByPlatformApplicationAsync(params)
        .then(function(data) {
          endpoints.push.apply(endpoints, data.Endpoints);
          if (data.NextToken) {
              return getEndpoints(data.NextToken, platformApplication, endpoints);
          } else {
              return endpoints;
          }
        });
    }