【问题标题】:firebase onAuthStateChanged following Fibonacci's series斐波那契系列之后的firebase onAuthStateChanged
【发布时间】:2018-01-09 19:24:36
【问题描述】:

我正在开发一个使用 Ionic 3 和 Firebase 作为身份验证提供程序的混合应用程序。该应用程序包含 2 个页面。一个登录页面和一个主页。在登录页面上有一个使用电子邮件+密码登录用户的按钮,在主页上有另一个按钮注销当前用户。基本上,第一次加载应用程序时一切正常。但是在登录然后注销然后再次登录之后,onAuthStateChange 内部的函数被调用两次,然后是 3 次,然后是 5 次,依此类推,遵循斐波那契数列。 这是登录页面代码:

firebase.auth().onAuthStateChanged(function(user) {
      if (user) {
        console.log('User logged-in');
        if (user.emailVerified) {
          self.goToHome();
        } else {
          self.showAlert();
          firebase.auth().signOut();
        }
      }
    });
  }

这是注销代码:

firebase.auth().onAuthStateChanged(function(user) {
      if (user == null) {
          console.log('User logged-out');
          navCtrl.push(WelcomePage);
        }
      });

chrome 控制台显示此行为:

(图片末尾的错误是我的错,因为我使用了错误的密码)

按钮调用的函数(但我 99% 确定问题出在 onAuthStateChanged):

  doLogin() {
    console.log('Trying to log in...');
    var email = this.account.email;
    var password = this.account.password;
    if (this.validateEmail(email) && password.length >= 8) {
      loading.present();
      firebase.auth().signInWithEmailAndPassword(email, password)
      .then(function(data) {
        loading.dismiss();
       });
}

logout() {
    firebase.auth().signOut();
  }

函数 goToHome 将用户移动到主页:

goToHome() {
    this.navCtrl.push(MainPage);
  }

Ben 在他的评论中指出的解决方案:

1:从 onAuthStateChanged 中移动所有与 navController 相关的函数 2:使用setRoot代替pop()和push()

goToHome() {
    this.navCtrl.setRoot(HomePage);
  }
logout() {
  firebase.auth().signOut();
  this.navCtrl.setRoot(WelcomePage);
}

3) 为了解决如果用户没有注销时能够自动登录的问题,我检查了 如果 firebase.auth().currentuser 存在,但使用超时,因为 Firebase 需要一些时间才能正常运行:

setTimeout(function(){
        var user = firebase.auth().currentUser;
        if (user != null) {
          self.goToHome();
        }
      }, 1500);

【问题讨论】:

  • 请同时提及您的component 路由逻辑。这是做什么self.goToHome();

标签: javascript angular firebase ionic-framework firebase-authentication


【解决方案1】:

我看到你在onAuthStateChanged 中推送页面。这可能会导致问题。

  1. 在第一个登录页面上,您创建 1 onAuthStateChanged login,当您点击登录时,您会推送 1 个新主页
  2. 在主页上,您创建 1 个onAuthStateChanged logout,当您单击注销时,您推送 1 个新登录页面(因此您有 2 个登录页面和 2 个onAuthStateChanged login 在单击后加载)
  3. 在新登录页面上单击登录后,您不会创建 1 个新的注销页面,而是创建 2 个,因为您已经有 2 个onAuthStateChanged login,所以这会导致加载 3 个注销页面和 3 个onAuthStateChanged logout
  4. 当您在新主页上单击注销时,您调用了 3 个onAuthStateChanged logout,从而创建了 3 个新登录页面 + 2 个现有登录页面 = 5
  5. 等等。

要测试是否是这种情况,您可以使用登录页面开始加载模块,登录时推送主页,注销时不要推送登录页面而是popToRoot()

希望对你有帮助,

【讨论】:

  • 使用popToRoot() 解决了一半的问题。基本上现在我有一个 WelcomPage 实例,但我仍然有多个 HomePage 实例。所以问题出在注销内部。
  • 奇怪,好在已经解决了一半,HomePage实例化了多少次?也像斐波那契?
  • 首页的行为和以前一样,意味着按照斐波那契数列进行实例化,但比以前增加了一半
  • 编辑上述评论:现在我重新检查了斐波那契系列已经停止,退出时它只是一个 +1 增量。
  • 我预计您的推送仍然存在问题,因为 popToRoot 取消了奇怪的行为并且推送再次启动它。您可以尝试将 push Home & poptoroot 更改为:this.navCtrl.setRoot(MainPage); & this.navCtrl.setRoot(WelcomePage);看看启动是否停止?
【解决方案2】:

您应该将用户发送到firebase.auth().signInWithEmailAndPassword(email, password) 之后的页面,而不是在侦听器上。 Firebase 监听器的行为很奇怪......

试试这个:

doLogin() {
    console.log('Trying to log in...');
    var email = this.account.email;
    var password = this.account.password;
    if (this.validateEmail(email) && password.length >= 8) {
        loading.present();
        firebase.auth().signInWithEmailAndPassword(email, password).then(function(data) {
            loading.dismiss();
            var user = firebase.auth().currentUser;
            if (user) {
                console.log('User logged-in');
                if (user.emailVerified) {
                    self.goToHome();
                } else {
                    self.showAlert();
                    firebase.auth().signOut();
                }
            } else {
            // No user is signed in.
            }
        }, function(error) {
        //error handling
        });
    }
}

【讨论】:

  • 我也想过这个解决方案,但是这样用户每次关闭页面时都必须进行身份验证
  • 一旦您启动应用程序并进入登录页面,请验证用户是否已经在那里,如果是,则无需询问凭据...
  • 已经尝试过这种方式,但 firebase 需要一些时间来初始化,所以我需要等待 x 时间才能检查用户是否已经在那里,这似乎不是一个优雅的解决方案
【解决方案3】:

我在登录时遇到了类似的问题。函数/侦听器firebase.auth().onAuthStateChanged( 将在每次身份验证状态更改时触发,我预计您的onAuthStateChanged 代码中的问题是firebase.auth().signOut(); 将触发一个新的onAuthStateChanged ...导致奇怪的初始行为。

您已经在注销按钮中放置了firebase.auth().signOut();,我建议您从登录页面上的onAuthStateChanged 中删除firebase.auth().signOut();,然后我预计斐波那契会停止(但您真的希望它停止吗?)

如果有任何结果,请告诉我。希望对你有帮助,

【讨论】:

  • 它没有解决问题,因为只有在未验证电子邮件时才调用signout(),事实并非如此
  • 嗯,也许是另一个问题:我看到你在推送页面,首先推送登录页面(编译第一个onAuthStateChanged,然后推送登录页面(不会破坏之前的登录页面),然后推送再次欢迎页面(=登录页面?)启动第二个 onAuthStateChanged ...当您再次登录时,您调用 2 onAuthStateChanged 它将推送 2 个主页,当您在该页面上注销时,您推送 1+2(从第一个和 2 个新的)欢迎页面,您可以在其中创建 2+3 用户登录...导致斐波那契数列
  • 我将this.navCtrl.push(WelcomPage) 更改为this.navCtrl.pop(),但现在应用程序在系列开始时崩溃,因为在第一次调用pop() 之后,第二次 ionic 找不到要弹出的页面。但是你说得对,推而不是弹出是错误的,仍然 onAuthStateChanged 会产生问题..
  • 在下面查看我的新解决方案,总而言之:您可以使用登录页面开始加载模块,登录时推送主页,注销时不要推送登录页面,但 PopToRoot
猜你喜欢
  • 2016-07-23
  • 2015-06-05
  • 2011-02-16
  • 2014-01-08
  • 2013-08-03
  • 2014-05-19
  • 2015-08-30
相关资源
最近更新 更多