Apparent race condition getting firebase.User from controller in Firebase 3.x

牧云@^-^@ 提交于 2019-12-12 00:42:00

问题


I'm using Firebase 3.x and the auth state change event to assign the current user in my service -

.service('FireService', function ($q, $http,$state) {

var accessToken;
var user;

firebase.auth().onAuthStateChanged(function (usr) {
  if (usr) {
    // User signed in!
    user = usr;
  } else {
    user = null;
    $state.go('login');
  }
});

return {

  currentUser: function () {
    return user;
  }
}

But I need the current user to a reference to my child objects from the database in the controller

var getLog = function () {
  var logRange = currentDate.format('MMMYYYY').toUpperCase();
  var userId = FireService.currentUser().uid;
  var ref = LogService.logs(userid,logRange);
  // download the data into a local object
  ref.once('value').then(
    function (result) {
      logObj = result;
    })
};

When I set breakpoints, I see that the currentUser() is always empty because the state change hasn't fired yet. I've also tried to assign my userid directly from firebase.User but this is also not yet initialized by the time my controllers are ready. How do I get the currently logged in user so that it's available before I start routing around in my app?


回答1:


I would recommend using the observer directly within the getLog method, so it waits until the current user is set:

var getLog = function () {
  var unsubscribe = firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      var logRange = currentDate.format('MMMYYYY').toUpperCase();
      var userId = user.uid;
      var ref = LogService.logs(userid,logRange);
      // download the data into a local object
      ref.once('value').then(
        function (result) {
          logObj = result;
        });
    }
    unsubscribe(); // So this observer is only triggered once.
  });
};

As the ref.once('value') resolves asynchronously anyway, it will just add a bit of latency to the method but won't change its behavior.

Using this "one off" observer pattern (an observer that calls its unsubscribe function the first time it is called) allows you to make sure Firebase Auth is fully initialized before executing the code. If Firebase Auth is already initialized by the time you create the observer, then its resolution will be triggered immediately. Remember that observers are always called asynchronously.

If you end up using this pattern often, you could add a method on FireService:

...
ready: function() {
  return $q(function(resolve, reject) {
    var unsubscribe = firebase.auth().onAuthStateChanged(function(user) {
      unsubscribe();
      resolve(user);
    });
  });
}
...

And use it within your getLog method:

var getLog = function () {
  FireService.ready().then(function(user) {
    if (!user) { return; }
    var logRange = currentDate.format('MMMYYYY').toUpperCase();
    var userId = user.uid;
    var ref = LogService.logs(userid,logRange);
    // download the data into a local object
    ref.once('value').then(
      function (result) {
        logObj = result;
      });
  });
};


来源:https://stackoverflow.com/questions/38054491/apparent-race-condition-getting-firebase-user-from-controller-in-firebase-3-x

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!