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?