简体   繁体   中英

Return from angular factory when ionic platform ready

I have a firebase Auth factory as follows

app.factory("Auth", ["$firebaseAuth", "FIREBASE_URL","$ionicPlatform",
  function($firebaseAuth, FIREBASE_URL, $ionicPlatform) {
      var auth = {};
      $ionicPlatform.ready(function(){
          var ref = new Firebase(FIREBASE_URL);
          auth = $firebaseAuth(ref);
      });
      return auth;
  }
]);

I am injecting the Auth factory in my ui-router resolve as dependency but by the time ui-router is configured the auth is empty because the platform ready kicks in afterwards.

app.config(function ($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('menu', {
      url: '/menu',
      abstract:true,
      cache: false,
      controller: 'MenuCtrl',
      templateUrl: 'templates/menu.html',
      resolve: {
        auth: function($state, Auth){
          //<--Auth is empty here when the app starts ----->
          return Auth.$requireAuth().catch(function(){
              $state.go('login'); //if not authenticated send back to login
          });
        }
      }
    })

How do i make sure the Auth factory is not empty before it is injected into ui-router?

I tried this -

app.factory("Auth", ["$firebaseAuth", "FIREBASE_URL","$ionicPlatform",
      function($firebaseAuth, FIREBASE_URL, $ionicPlatform) {
          return $ionicPlatform.ready(function(){
              var ref = new Firebase(FIREBASE_URL);
              return $firebaseAuth(ref);
          });
      }
    ]);

But this returns a promise which makes it even more complicated to use.

EDIT : I used promises in factory to fix the problem

app.factory("Auth", ["$firebaseAuth", "FIREBASE_URL","$ionicPlatform","$q",
  function($firebaseAuth, FIREBASE_URL, $ionicPlatform, $q) {
    var auth = {};
    return {
      getAuth : function(){
        var d = $q.defer();
        $ionicPlatform.ready().then(function(){
          var ref = new Firebase(FIREBASE_URL);
          auth = $firebaseAuth(ref);
          d.resolve(auth);
        });
        return d.promise;
      }
    };
  }
]);

This works but I am looking for a better solution.

You can't return {} and then later expect that to magically become the $firebaseAuth instance, which is later set in an asynchronous function. See this question for some async education.

// "points" the x variable to object A
var x = {};
// "points" the x variable to an instance of $firebaseAuth()
// but not before {} is returned from the function
x = $firebaseAuth(...)

If you want to wait until the platform is ready before your resolve function is run, then simply chain the promises; that's pretty much the point of promises.

app.factory('IonicReady', function($q, $ionicFramework) {
   return $q(function(resolve, reject) {
      $ionicPlatform.ready(resolve);
   });
});

And then in your resolve:

resolve: {
   auth: function($state, Auth, IonicReady){
     return IonicReady
        .then(function() {
            return Auth.$requireAuth();
        })
        .catch(function(e) {
            console.error(e);
            $state.go('login');
        });
  }
}

Not being an Ionic expert, this simply begs the question: Why bootstrap Angular at all before Ionic is ready? Why is Angular not bootstrapped automatically when Ionic is loaded? It seems more appropriate to not perform any routing until the platform is ready to support this and to simplify the process from the gate. I don't know how to execute that part, but it seems like it solves the X rather than the Y .

Be sure to check out the official Firebase documentation and examples on https://www.firebase.com/docs/web/libraries/angular/guide/user-auth.html

 resolve: {
  // controller will not be loaded until $waitForAuth resolves
  // Auth refers to our $firebaseAuth wrapper in the example above
  "currentAuth": ["Auth", function(Auth) {
    // $waitForAuth returns a promise so the resolve waits for it to complete
    return Auth.$waitForAuth();
  }]
}

Your Auth factory can look like this then

app.factory("Auth", ["$firebaseAuth",
  function($firebaseAuth) {
    var ref = new Firebase("https://docs-sandbox.firebaseio.com");
    return $firebaseAuth(ref);
  }
]);

without a dependency on the ionic platform itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM