0

I'm trying to wait till all the call back are completed. However, the counter is not being decremented. How do I fix this?

var counter = json.length;

for(i=0;i<json.length;i++){
    FB.api("url",function(response){
        doSomething(response);
        counter = counter - 1;
    });
}

while(counter>0){
    alert(counter);
}

In the above code the counter value is staying the same as json.length.

user3587180
  • 1,317
  • 11
  • 23
  • How is foo.api implemented? If it returns a promise you could look at using something like Promise.all. – ACOMIT001 Mar 15 '17 at 01:05
  • asynchronous code strikes again. – Jaromanda X Mar 15 '17 at 01:06
  • I updated the code. I'm using Facebook graph api. It takes in a callback function. – user3587180 Mar 15 '17 at 01:07
  • Is there any error after `FB.api` returns, like in `doSomething(response)`? – TheVillageIdiot Mar 15 '17 at 01:08
  • @TheVillageIdiot the code works fine - no errors returned. It is because of the call back function the counter value is not being reduced. Code is stuck at an infinite loop at the while section. – user3587180 Mar 15 '17 at 01:08
  • Here's the issue ... you never let FB.api run, because of your synchronous while loop hogging all the resources – Jaromanda X Mar 15 '17 at 01:10
  • I suspect you want to "wait" until all the requests have completed before continuing on ... you need to know how to deal with asynchronous code – Jaromanda X Mar 15 '17 at 01:11
  • @JaromandaX wow nice catch. didn't think about it at all. Is there a way for me to wait till the fb api runs? Please post this as an answer. I'll accept it. – user3587180 Mar 15 '17 at 01:11
  • @user3587180 possible using recursive, function calling itself. – Gene Lim Mar 15 '17 at 01:14
  • Possible duplicate of [Wait until all jQuery Ajax requests are done?](http://stackoverflow.com/questions/3709597/wait-until-all-jquery-ajax-requests-are-done) – JJJ Mar 15 '17 at 09:28

2 Answers2

4

Here's the issue ... you never let FB.api run, because of your synchronous while loop hogging all the resources

A simplistic approach would be as follows

var counter = json.length;

for (i=0;i<json.length;i++){
    FB.api("url",function(response){
        doSomething(response);
        counter = counter - 1;
        if(counter == 0) {
            allDone();
        }
    });
}

where allDone is a function to run once all FB.api have completed

A modern approach would probably use Promises - perhaps like this

Promise.all(json.map(function(item) {
    return new Promise(function(resolve, reject) {
        FB.api("url",function(response){
            doSomething(response);
            resolve(response);
        });
    });
})).then(function(results) {
    // all done at this point, results is an array of responses from above
});

Or, as @Bergi pointed out

Promise.all(json.map(item => 
    new Promise(resolve => 
        FB.api("url", resolve)
    )
    .then(doSomething)
))
.then(function(results) {
    // all done at this point, results is an array of responses from above
});

(ES5 version here)

Promise.all(json.map(function(item) {
    return new Promise(function(resolve, reject) {
        FB.api("url", resolve);
    }).then(doSomething);
})).then(function(results) {
    // all done at this point, results is an array of responses from above
});

This assumes, however, that the callback in FB.api only ever gets a single argument - i.e. what to do in the case of an error?

Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • `return new Promise(resolve => { FB.api("url", resolve) }).then(doSomething)` – Bergi Mar 15 '17 at 01:27
  • yeah, that too @Bergi :p I thought perhaps the `FB.api` call in the question was "simplified", there doesn't seem to be any error checking done in the question - your cleaner solution may not be appropriate (I just don't know `FB.api` well enough to make a judgement call) – Jaromanda X Mar 15 '17 at 01:33
-3
var counter = json.length;

for(i=0;i<json.length;i++){
    FB.api("url",function(response){
        doSomething(response);
        counter = counter - 1;
        while(counter>0){
                Alert (counter)
         }
    });
}
Brandon
  • 1,747
  • 2
  • 13
  • 22