-1

I am trying to determine through some flag when this asynchronous function ends.

This is how I call my function:

// Calling the function in a loop
for (var i=0,l=myIds.length; i<l; ++i) {
    install(pageId, myIds[i], apps_num[''+myIds[i]], <?php echo $this->comid ?>, '<?php echo $this->site_url; ?>');
}

And this is my function:

install: function(pageId, appId, app_num, com_id, siteurl) {
    FB.getLoginStatus(function(response) {
        // Checking if connected to Facebook
        if (response.status === 'connected') {
            var uid = response.authResponse.userID;
            console.log(response.authResponse);
            var userAccessToken = response.authResponse.accessToken;

            // Get page access token
            FB.api('/'+pageId+'?fields=access_token='+userAccessToken, function(response) {
                var pageAccessToken = response.access_token;

                // Get information if user got this application
                FB.api('/'+pageId+'/tabs/'+appId+'?access_token='+pageAccessToken,
                    function(data) {
                        if (data.data.length < 1) {
                            console.log("Not installed, Installing...");

                            // Install the application
                            var params = {};
                            params['app_id'] = appId;
                            FB.api('/'+pageId+'/tabs?access_token='+pageAccessToken, 'post', params, function(response) {
                                if (!response || response.error) {
                                    console.log("Error Installing!");
                                }
                                else {
                                    console.log("Installed :)");
                                }
                            });
                        }
                        else {
                            console.log("Already installed.");
                        }
                    });
                });
            }
            else
                if (response.status === 'not_authorized') {
                    console.log("the user is logged in to Facebook, but not connected to the app.");
                }
                else {
                    console.log("the user isn't even logged in to Facebook.");
                }
            });
        }

How can I solve this issue? I tried to use static variables, but I wasn't able to call them inside the asynchronous function..

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
D_R
  • 4,894
  • 4
  • 45
  • 62
  • 3
    When the callback is called, you know it's finished. – Pointy Feb 21 '12 at 16:30
  • possible duplicate of [Is there a way to detect if the Facebook Javascript SDK loaded successfully?](http://facebook.stackoverflow.com/questions/5334977/is-there-a-way-to-detect-if-the-facebook-javascript-sdk-loaded-successfully) – ifaour Feb 21 '12 at 17:11

3 Answers3

3

The usual thing is to have any code that needs to know the outcome of an asynchronous call pass a function reference into the call, which the function then calls when it's done (a "callback").

So in your case, you'd add a callback parameter to your install function:

install: function(pageId, appId, app_num, com_id, siteurl, callback)
//                                        here ------------^

...and then call it when appropriate from the callbacks you're passing into FB.getLoginStatus and/or FB.api, e.g. something like this:

install: function(pageId, appId, app_num, com_id, siteurl, callback) {
        FB.getLoginStatus(function(response) {
                       // checking if connected to facebook
              if (response.status === 'connected') {
                var uid = response.authResponse.userID;
                console.log(response.authResponse);
                var userAccessToken = response.authResponse.accessToken;

                // get page access token
                FB.api('/'+pageId+'?fields=access_token='+userAccessToken, function(response) {
                    var pageAccessToken = response.access_token;

                    // get information if user got this app
                    FB.api('/'+pageId+'/tabs/'+appId+'?access_token='+pageAccessToken,
                       function(data) {
                         if (data.data.length < 1) {
                             console.log("Not installed, Installing...");

                            // install the app
                             var params = {};
                             params['app_id'] = appId;
                             FB.api('/'+pageId+'/tabs?access_token='+pageAccessToken, 'post', params, function(response) {
                                 if (!response || response.error) {
                                    callback(false, "Error installing");
                                    console.log("Error Installing!");
                                 } else {
                                    callback(true, "Installed");
                                    console.log("Installed :)");

                                 }
                                });
                         }
                         else {
                             callback(false, "Already installed.");
                             console.log("Already installed.");
                         }
                     });
                });
              } else if (response.status === 'not_authorized') {
                callback(false, "Logged in but not connected.");
                console.log("the user is logged in to Facebook, but not connected to the app.");
              } else {
                callback(false, "Not logged in.");
                console.log("the user isn't even logged in to Facebook.");
              }
             });
      }

There I've given the callback function two arguments: A boolean saying whether the installation was performed, and a status message.

Mike
  • 2,567
  • 3
  • 23
  • 35
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

First, you add an extra param to your function, that will receive a function object

install: function(pageId, appId, app_num, com_id, siteurl, callbackFunction) {

Then, inside the function install, after

console.log("Installed :)");

you add

callbackFunction();

This way, when you call the install function:

for (var i=0,l=myIds.length; i<l; ++i) {
    install(pageId, myIds[i], apps_num[''+myIds[i]], <?php echo $this->comid ?>, '<?php echo $this->site_url; ?>', function(){
        //do whatever you want;
    });
}
André Alçada Padez
  • 10,987
  • 24
  • 67
  • 120
1

jQuery does it by letting the user determine how a function should react when a function is finished. This means, putting a function as a parameter. This is called a callback

function install(pageId, appId, app_num, com_id, siteurl, pCallback) {
    //Doing cool stuff.
    //OK, I am finished.
    pCallback(a, b, c)
}

function lefinish(a, b, c) {
    alert(b);
}

// Calling install
install(pageId, appId, app_num, com_id, siteurl, lefinish)

As an added bonus, if you really need to know exactly what happened, you can put multiple functions in it, depending on the success of your first function

function install(pageId, appId, app_num, com_id, siteurl, pCallback) {
    //Doing awesome stuff
    if (response.status === 'connected') {
        if (typeof(pCallback.onConnect) == 'function') {
           pCallback.onConnect(a,b,c);
        }
    }
    else
        if (response.status === 'not_authorized') {
            if (typeof(pCallback.onNoAuth) == 'function') {
                pCallback.onNoAuth(a,b,c);
            }
        }
        else {
            if (typeof(pCallback.onNotLoggedIn) == 'function') {
                pCallback.onNotLoggedIn(a,b,c);
            }
        }
}

function lefinish(a, b, c) {
   alert(b);
}

// Calling install
install(pageId, appId, app_num, com_id, siteurl, {
    'onConnect': function(a,b,c) {}, //Anonymous function
    'onNoAuth': lefinish //A predefined function
    // does not produce an error if onNotLoggedIn is not defined because of typeof().
})
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike
  • 2,567
  • 3
  • 23
  • 35