Asynchronous method in while loop with Graph API paged

2.1k Views Asked by At

I'm using facebook node sdk for node.js to get information from a facebook user such as their feed and friends, which is working fine.

However I'm having an issue where the returned data is paged - I need to build something in recursive mode. Let me explain:

FB.api('/me/feed?limit=5000', {
    access_token: token
}, function(response) {
  // response is an object that could have as response.paging.next attribute
}); 

Limit isn't working here, because it returns a max of 245 and returns paging object indicating the next page of results.

Because the next call depends of the result of the previous async call, I tried to do something like this:

// first call before
var hasNext = response.paging.next ? true : false;
while (hasNext){
    FB.api('/me/feed', {
        access_token: token
    }, function(response_paged) {
       response.data.concat(response_paged.data);
       // If do not have a next page to break the loop
       if (!response_paged.paging.next) hasNext = false;
    });
} 

The way the next token was obtained is not important for now

The point is I'm trying to do async calls in recursive mode, but its not working, this way I'm getting an infinite loop.

3

There are 3 best solutions below

8
On BEST ANSWER

My idea of solving this with async/await:

async function getFeed(token) {
    let feedItems = [],
        hasNext = true,
        apiCall = '/me/feed';

    while (hasNext) {
        await new Promise(resolve => {
            FB.api(apiCall, {access_token: token}, (response) => {
                feedItems.concat(response.data);
                if (!response.paging.next) {
                    hasNext = false;
                } else {
                    apiCall = response.paging.next;
                }
                resolve();
            });
        });
    }
    return feedItems;
}

getFeed().then((response) => {
    console.log(response);
});

Be aware that you need Node.js 7.9.0+ for this: http://node.green/

For older versions, install this: https://github.com/yortus/asyncawait

You can also use a recursive function, but the smooth/modern way would be async/await.

1
On

Instead of using:

feedItems.concat(response.data);

I have made: (if is the case on response.data has the data)

for(var i in response.data){
   feedItems.push(response.data[i]);
}
0
On

As of today (12/10/21) response.data is of type Object. The below would now be appropriate for saving response data.

for (let d of response.data) {
  feedItems.push(d)
}