明显的竞赛状况从Firebase 3.x中的控制器获取firebase.User [英] Apparent race condition getting firebase.User from controller in Firebase 3.x

查看:207
本文介绍了明显的竞赛状况从Firebase 3.x中的控制器获取firebase.User的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Firebase 3.x和auth状态更改事件来为我的服务分配当前用户 -


$ b

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

  var accessToken; 
var user;

firebase.auth()。onAuthStateChanged(函数(usr){
if(usr){
//用户登录!
user = usr;
} else {
user = null;
$ state.go('login');
}
});

return {

currentUser:function(){
return user;
}
}

但是我需要当前用户从控制器的数据库中引用我的子对象。
$ b $ $ $ $ $ p $ var $ getLog = function (){
var logRange = currentDate.format('MMMYYYY')。toUpperCase();
var userId = FireService.currentUser()。uid;
var ref = LogService.logs(userid ,logRange);
//将数据下载到本地对象
ref.once('value')。then(
函数(结果){
logObj =结果;
})
};

当我设置断点时,我发现currentUser()总是空的,因为状态变化hasn'还没有开火我也尝试直接从firebase.User分配我的用户ID,但是这还没有被我的控制器准备好的时候初始化。我如何获取当前登录的用户,以便在我的应用程序开始路由之前可用?我建议直接在 getLog 方法中使用观察者,所以它一直等到当前用户设置:

  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);
//将数据下载到本地对象
ref.once('value')。then(
function (result){
logObj = result;
});
}
unsubscribe(); //所以这个观察者只触发一次
});
};

由于 ref.once('value')无论如何都是异步解析的,它只会给方法增加一些延迟,但不会改变它的行为。



使用这个one off观察者(在第一次调用它时调用它的 unsubscribe 函数的观察者)允许您确保在执行代码之前完全初始化Firebase身份验证。如果Firebase身份验证在您创建观察者时已经初始化,则其分辨率将立即触发。请记住,观察者总是被异步调用。



如果您最终经常使用这个模式,您可以在FireService上添加一个方法:



$ $ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ .auth()。onAuthStateChanged(function(user){
unsubscribe();
resolve(user);
});
});
}
...

getLog 方法:

  var getLog = function(){
FireService.ready ()函数(用户){
if(!user){return;}
var logRange = currentDate.format('MMMYYYY')。toUpperCase();
var userId = user.uid;
var ref = LogService.logs(userid,logRange);
//将数据下载到本地对象
ref.once('value')。then(
函数(结果){
logObj =结果;
});
});
};


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?

解决方案

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;
      });
  });
};

这篇关于明显的竞赛状况从Firebase 3.x中的控制器获取firebase.User的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆