尽管有外部声明,但从全球看不到firebase数据库的变量。 (JavaScript的)

问题描述 投票:0回答:1

我过去几个小时一直在研究局部变量和全局变量。我从这个问题“How do I change the value of a global variable inside of a function”和其他一些问题中发现,如果变量是在函数之前声明的(在它之外),那么当你想要更新函数中的变量时,你只需要说“变量=空白”而不是“var”继续进行。

如果您查看下面的函数,我有三个警报,所有警报都通过firebase警告当前登录用户的用户名。 firebase引用中的第一个警报显示用户名没问题。另外两个警告“未定义”。我需要能够在所有三个位置引用变量,我做错了吗?还是有另一种方法可以做到这一点,也许更有效率?

var database = firebase.database();
var username;

function initApp() {
  // Listen for auth state changes.
  // [START authstatelistener]
  firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      // User is signed in.
      var displayName = user.displayName;
      var email = user.email;
      var emailVerified = user.emailVerified;
      var photoURL = user.photoURL;
      var isAnonymous = user.isAnonymous;
      var uid = user.uid;
      var providerData = user.providerData;

      var ref = firebase.database().ref("users/" + uid);
      ref.once("value").then(function(snapshot) {
        username = snapshot.child("username").val();
        alert(username);
      });
      alert(username);
    }
  });
}
alert(username);

window.onload = function() {
  initApp();
};

我理解这可能与其他问题类似,但尽管有许多不同的方法,但这些答案似乎并不起作用。在此先感谢您的所有帮助,我希望这只是一个愚蠢的错误。

javascript firebase firebase-realtime-database global-variables
1个回答
1
投票

我认为您对代码的异步性质感到困惑。您的用户名仅在回调中可用:

ref.once("value").then(function(snapshot) {
  username = snapshot.child("username").val();
  alert(username);
});

因为ref.once("value")是异步的(紧跟在上面代码块之后的alert将始终在你的.then回调执行之前被调用)。任何依赖于username的代码都必须确保在执行之前完成异步调用。

有很多方法可以实现这一点,例如:async/await,从Promise函数返回initApp,或者更改initApp以接受在异步内容完成后运行依赖代码的回调。这是一个返回Promise的示例:

function initApp() {
  return new Promise(function(resolve, reject) {
    // Listen for auth state changes.
    // [START authstatelistener]
    firebase.auth().onAuthStateChanged(function(user) {
      if (user) {
        // User is signed in.
        var displayName = user.displayName;
        var email = user.email;
        var emailVerified = user.emailVerified;
        var photoURL = user.photoURL;
        var isAnonymous = user.isAnonymous;
        var uid = user.uid;
        var providerData = user.providerData;

        var ref = firebase.database().ref("users/" + uid);
        ref.once("value").then(function(snapshot) {
          username = snapshot.child("username").val();
          resolve(username);
        });
      } else {
        // no username, reject
        reject("User is not logged in")
      }
    });
  });
}

window.onload = function() {
  initApp().then(function(username) {
    alert(username);
    // do things that depend on user/username
  }).catch(function(error) {
    alert(error);
  });
};

一旦Promise到位,您可以使用async/await让您的代码感觉更加同步:

window.onload = async function() {
  try {
    const username = await initApp();
    alert(username);
  } catch(e) {
    alert(e);
  }
};

请记住,您仍然无法在此函数之外使用alert用户名 - 依赖于异步数据的任何代码必须等到该数据准备就绪,即在then / callback / etc中处理。

© www.soinside.com 2019 - 2024. All rights reserved.