1

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.

Jack
  • 2,891
  • 11
  • 48
  • 65
BrTkCa
  • 4,703
  • 3
  • 24
  • 45

3 Answers3

6

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.

andyrandy
  • 72,880
  • 8
  • 113
  • 130
  • Doesn't works @luschn. I tried also with a simple loop a counter and when is it to set 30 for example to stop, but still blocked in loop. – BrTkCa Apr 26 '17 at 20:40
  • you can´t use a simple loop, you have to wait for each callback. either with a recursive function or async/await. what do you mean by "doesn´t work"? did you debug my code? i can test it later, but a more detailed explanation would be helpful if it does not work. any errors? – andyrandy Apr 27 '17 at 08:37
  • No errors, the code runs, but it's as `await` block do not wait the response of API, I think I'm doing something wrong.. – BrTkCa Apr 27 '17 at 15:12
  • what node.js version are you using? – andyrandy Apr 28 '17 at 09:11
  • Version 7.9 nodejs – BrTkCa Apr 28 '17 at 10:59
  • and the function is defined as "async"? – andyrandy Apr 28 '17 at 11:01
  • ah, now i get it. sorry, my mistake. FB.api does not return a promise. i will fix the code. – andyrandy Apr 28 '17 at 11:01
  • Ohh, that's worked! Thanks! Only curiosity..this works with node.js 7.6? – BrTkCa Apr 28 '17 at 12:39
1

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]);
}
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Emily Luna
  • 11
  • 1
  • Although this isn't the issue of the questions, thank you for the good catch when concating. – BrTkCa Nov 06 '18 at 10:08
0

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)
}