【问题标题】:How do I correctly use Firebase's .once() method to store the retrieved value in Javascript?如何正确使用 Firebase 的 .once() 方法将检索到的值存储在 Javascript 中?
【发布时间】:2017-11-25 07:18:56
【问题描述】:

编辑:以下不是我真正的问题。查看答案。

我正在使用 Google firebase 开发一个简单的 html/javascript 聊天客户端。以下代码旨在成为注册和登录用户的基本系统,其中该函数在12 位置提供了一个包含用户名和密码的数组($usr)。

然后根据数据库的结果(getuser 变量,结构为用户 obj)检查本地用户名和密码 $usr[1-2],以确定用户名是否已被使用或用户的凭据是否有效。请注意,这是一个个人项目,数据并非敏感数据。

//Registers user credentials with input [cmd, user, pass]
var auth = function ($usr) {
	var db = firebase.database().ref('chatapp/users/' + $usr[1]);
	var getuser;
	user = {'name': $usr[1], 'pass': $usr[2]};
	db.once('value').then(function(snapshot) {
		getuser = snapshot.val();
		if ($usr[0] === "/register") {
			if (getuser.name !== $usr[1]) {
				db.set(user);
				notify('Registered ' + $usr[1] + ' with pass "' + $usr[2] + '"');
			} else {
				notify('Username "' + $usr[1] + '" already taken, try again');
			}
		} else if ($usr[0] === "/login") {
			if (getuser.name !== $usr[1] || getuser.pass !== $usr[2]) {
				notify('Invalid credentials ' + $usr[1] + ':' + $usr[2]);
			} else {
				notify($usr[1] + ' logged in');
			}
		}
	});
	
};

问题在 db.once() 中起作用。正在检索数据,但已延迟。如果用户尝试注册 (getuser.name !== $usr1) 将始终返回 True,因为该变量设置为未定义。但是,登录命令完美无缺,因为此时 getuser 已设置为从 Firebase 检索到的值。

我尝试过仅使用 .once() 来设置变量,或者作为返回 snapshot.val() 的函数。我尝试将我的所有代码包含在 .once() 的回调中,并使用 snapshot.val()[name] 和 [pass] 而不是将其存储到变量中。唯一的解决方案似乎是手动中断程序流程。

此外,我还发现在 getuser.name 有效的情况下,使用 getuser[name] 不起作用,这毫无意义,进一步激怒了我。请帮忙,现在是凌晨 2 点 12 分。

Here is the official documentation. Here is a relevant Stackoverflow question, which may be the solution I'm looking for but I don't understand it.

真正让我感到困惑的是,.then 后面的函数据说依赖于被确认的数据,显然事实并非如此。

【问题讨论】:

  • 获得快照后,数据不会延迟。您存储在变量中。您在某个地方还有另一个问题,但我无法很好地理解您的问题
  • @abeyaz 我告诉你事实并非如此。如果我在将快照保存到变量后立即发出警报,它将返回未定义。如果我稍后在流程中添加第二个警报,它将返回正确的对象。如果命令是 /register,getuser.name !== $usr[1] 将始终返回 true,但 /login 中的相同语句返回 true 或 false,具体取决于 getuser.name 的值(在第一个循环。
  • 请把console.log(snapshot.val(), getuser) 放在getuser = snapshot.val(); 后面。因此,我们可以看到正在发生的事情并提出解决方案。
  • 感谢您的帮助。我找到了一个我将更新的解决方案,我认为你是正确的,但它有一些怪癖。

标签: javascript database firebase asynchronous firebase-realtime-database


【解决方案1】:

这是对我有用的代码:

//Registers user credentials with input [cmd, user, pass]
var auth = function ($usr) {
	var db = firebase.database().ref('chatapp/users/' + $usr[1]);
	var getuser;
	user = {'name': $usr[1], 'pass': $usr[2]};
	db.once('value').then(function(snapshot) {
		getuser = snapshot.val();
		if ($usr[0] === "/register") {
			if (getuser === null) {
				db.set(user);
				notify('Registered ' + $usr[1] + ' with pass "' + $usr[2] + '"');
			} else {
				notify('Username "' + $usr[1] + '" already taken, try again');
			}
		} else if ($usr[0] === "/login") {
			if (getuser.name !== $usr[1] || getuser.pass !== $usr[2]) {
				notify('Invalid credentials ' + $usr[1] + ':' + $usr[2]);
			} else {
				notify($usr[1] + ' logged in');
			}
		}
	});
};

这个问题实际上不是我的问题。是什么让我相信数据的检索被延迟是因为我的代码最初位于 .once() 方法的回调函数之外。如果您使用.once() 的回调函数将snapshot.val() 写入变量,然后将其余代码写入回调函数之外,则数据将异步写入并且您的变量将设置为undefined,直到真值可以从服务器检索。我相信解决此问题的方法是从回调中调用带有参数snapshot.val() 的函数,或者只是在回调中编写代码(如上)。

我的代码的实际问题在于if (getuser.name !== $usr[1]) 行。如果getuser 的值为null,这将导致错误。固定代码如上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 2016-12-15
    • 2011-12-28
    • 2020-08-01
    相关资源
    最近更新 更多