尽管有外部声明,但仍无法全局查看Firebase数据库中的变量. (javascript) [英] Variable from firebase database isn't seen globally despite outer declaration. (javascript)

查看:56
本文介绍了尽管有外部声明,但仍无法全局查看Firebase数据库中的变量. (javascript)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

过去的几个小时中,我一直在研究局部和全局变量.我从这个问题中发现的内容"

I have been doing research for the past few hours on local and global variables. What I found from this question "How do I change the value of a global variable inside of a function", and a few others was that if the variable was stated before the function (outside of it) then when you want to update the variable in a function you just say the "variable = blank" without "var" proceeding it.

如果您查看下面的功能,我有三个警报,所有警报都通过firebase来警告当前登录用户的用户名. firebase引用中的第一个警报显示用户名没问题.其他两个警报未定义".我需要能够在所有三个位置引用该变量,我做错了什么吗?还是有另一种方法可以有效并且可能更有效?

If you look at the function below I have three alerts, all alerting the username of the currently logged in user via firebase. The first alert, inside the firebase reference, displays the username no problem. The other two alert "undefined". I need to be able to reference the variable in all three locations, is there something I did wrong? or is there another way to do this that works and is maybe more efficient?

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

我了解这似乎与其他问题相似,但是尽管有许多不同的方法,但这些答案似乎并没有奏效.预先感谢您的所有帮助,我希望这只是一个愚蠢的错误.

I understand this may seem similar to other questions, but those answers didn't seem to work despite numerous different approaches. Thanks in advance for all of your help, I am hoping this is just a stupid mistake.

推荐答案

我认为您对代码的异步性质感到困惑.您的用户名只能在此处的回调中使用:

I think you are confused about the asynchronous nature of your code. Your username is only going to be available in the callback here:

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

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

because ref.once("value") is asynchronous (the alert immediately following the code block above will always be called before your .then callback executes). Any code that depends on username is going to have to ensure that the asynchronous call is complete before executing.

有多种方法可以完成此操作,例如:async/await,从initApp函数返回Promise或更改initApp以接受在异步操作后运行依赖代码的回调做完了.这是一个返回Promise的示例:

There are a number of ways to accomplish this, such as: async/await, returning a Promise from your initApp function, or changing initApp to accept a callback that runs your dependent code once the async stuff is complete. Here is an example that returns a 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,您可以使用

Once the Promise is in place, you can use async/await to make your code feel more synchronous:

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

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

Keep in mind that you will still not be able to alert the username outside of this function - any code that relies on the async data must wait until that data is ready i.e. be handled in a then/callback/etc.

这篇关于尽管有外部声明,但仍无法全局查看Firebase数据库中的变量. (javascript)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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