问题
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