如何等待Firebase实时数据库迭代停止?

问题描述

所以我有以下代码

var users = db.ref("/usr")
var userE = "a@a.com"
var counter = 0;
users.once("value").then(function(snap) {
   snap.forEach(function(childSnapshot){
     var data = childSnapshot.val()
     var emailA = data.email
     if(emailA == userE){
       counter++
     }
   })
})
console.log(counter)

我的问题不在于迭代,似乎可以做到。但是,令我感到困惑的是,即使数据库中存在userE,我的计数器似乎也没有增加(这意味着它始终保持为0)。似乎console.log在.forEach循环完成之前发生。我怎样才能解决这个问题?如果没有真正的解决方法,如何验证用户的电子邮件尚未存在于数据库中?

此外,我已经确保emailA的值确实是来自数据库的电子邮件。看来实际的问题只是等待循环完成而已。

解决方法

您的问题不在于firebase,而是异步/诺言如何在javascript中工作。

JS不会等待promise中的代码被执行,因此您的日志在.then调用甚至开始之前就已完成!

为了使事情更清晰,您应该将所有counter代码移到回调中:

var users = db.ref("/usr")
var userE = "a@a.com"
users.once("value").then(function(snap) {
   // once this callback is executed we are back to synchronous code
   var counter = 0;
   snap.forEach(function(childSnapshot){
     // this forEach callback is actually synchronous,unlike .then promises
     var data = childSnapshot.val()
     var emailA = data.email
     if(emailA == userE){
       counter++
     }
   })

   // we can now access our counter
   console.log(counter);
})

console.log('this will be log before the counter!')

,

问题不在于 Firebase ,而是异步操作。 检查this,了解JS中的Promises的工作原理!

以下是使用ES6语法的示例:

const dbRef = db.ref("/usr");
const email = "a@a.com";

const checkIfUserIsInDatabase = async (users,email) => {
    let result = false;
    
    const data = await users.once("value");

    data.forEach(user => {
        if(user.val().email === email) result = true;
    })

    return result;
};

checkIfUserIsInDatabase(dbRef,email).then((isUserInDatabase) => {
    if(isUserInDatabase) {
        console.log("Hell yeah!");
    } else {
        console.log("No :(");
    }
});