How to initialize facebook sdk and parse for parse.com facebook login in angularjs $app.run and factory/service.

Functions in the controller can then be used by making sure that both libs have been loaded and initialized. Solution to the following errors

```
You need to call Parse.initialize before using Parse.
The Facebook JavaScript SDK must be loaded before calling init.
```

#### constants.js

```
angular.module('constants', [ ])
.constant('ENVIRONMENT', 'development')
.constant('FACEBOOK_SMM_APP_ID', '123456789')
.constant('FACEBOOK_SMM_SCOPES', 'email, user_friends, user_photos,user_birthday,user_work_history,user_education_history,user_about_me,user_interests,user_hometown,user_likes')
.constant('PARSE_SMM_APP_ID', 'abcdefghijklmnop')
.constant('PARSE_SMM_JAVASCRIPT_KEY', 'abcdefghijklmnop')
```

#### app.js

```
angular.module('starterApp', ['ngRoute', 'constants', 'me'])

.config(function($routeProvider) {
    // whatever your routes
})


.run(['$rootScope', '$location', function ($rootScope,$location, FACEBOOK_SMM_APP_ID, PARSE_SMM_APP_ID, PARSE_SMM_JAVASCRIPT_KEY) {
        // material works with arrive js
        $.material.init();

      window.fbAsyncInit = function() {
        window.fbApiInit = true;
        $rootScope.fbApiInit = true;
      };

      (function(d, s, id){
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {return;}
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));

        $rootScope.$on('$routeChangeStart', function (event) {
            console.log("App Run")
            // if (!Auth.isLoggedIn()) {
            //     console.log('DENY');
            //     event.preventDefault();
            //     $location.path('/login');
            // }
            // else {
            //     console.log('ALLOW');
            //     $location.path('/home');
            // }
            //
        })

        angular.element(document).ready(function () {
            $("body").tooltip({ selector: '[data-toggle=tooltip]' });

        });

}])


.service('appInitFactory', function($q, $rootScope, FACEBOOK_SMM_APP_ID, PARSE_SMM_APP_ID, PARSE_SMM_JAVASCRIPT_KEY) {

    function fbEnsureInit(callback) {
        if( ! $rootScope.fbApiInit ) {
            setTimeout(function() {fbEnsureInit(callback);}, 50);
        } else {
            callback();
        }
    }

    function parseEnsureInit(callback) {
        Parse.initialize(PARSE_SMM_APP_ID, PARSE_SMM_JAVASCRIPT_KEY);
        if (! Parse.applicationId ) {
            setTimeout(function() {parseEnsureInit(callback);}, 50);
        } else {
            callback();
        }
    }

    function fbAndParseEnsureInit (callback) {
        parseEnsureInit(function(){
            if (!$rootScope.fbApiInit) {
                setTimeout(function() {fbAndParseEnsureInit(callback);}, 50);
            } else {
                Parse.FacebookUtils.init({ // this line replaces FB.init({
                    appId: FACEBOOK_SMM_APP_ID, // Facebook App ID
                    status: true, // check Facebook Login status
                    cookie: true, // enable cookies to allow Parse to access the session
                    xfbml: true, // initialize Facebook social plugins on the page
                    version: 'v2.2' // point to the latest Facebook Graph API version
                });
                callback();
            }
        })
    }

    // Promise-based API
    return {
        facebookInitialize: function(callback) {
            var deferred = $q.defer();
            fbEnsureInit(function(){
                deferred.resolve(true);
            })
            return deferred.promise;
        },
        parseInitialize: function(callback) {
            var deferred = $q.defer();
            parseEnsureInit(function(){
                deferred.resolve(true);
            })
            return deferred.promise;
        },
        fbAndParseInitialize: function(callback) {
            var deferred = $q.defer();
            fbAndParseEnsureInit(function(){
                deferred.resolve(true);
            })
            return deferred.promise;
        }
    };

})
```


#### me.js

```
angular.module('me', ['starterApp.directives'])
.controller('MeController', function(appInitFactory, $scope, $routeParams,$log, ENVIRONMENT, FACEBOOK_SMM_APP_ID, PARSE_SMM_APP_ID, PARSE_SMM_JAVASCRIPT_KEY) {

    appInitFactory
        .facebookInitialize()
        .then(function(ret) {
            console.log("this will be run once just FB is initialized");
        })

    appInitFactory
        .fbAndParseInitialize()
        .then(function(ret) {
            console.log("this will be run once FB & Parse are initialized");

            FB.api('/me', function(response) {
                console.log(response);
            });
        })
})
```