检索数据时,javascript+firebase 函数因操作顺序不同导致的return值不正确,如何解决?

How to solve incorrect return value of javascript+firebase function due to order of operation is different when retrieving data?

我目前正在实现一个 javascript 函数来判断用户 ID 和名称是否匹配。

function name_match(user_id, user_realname) {
    var dbref = firebase.database().ref();
    var namesref = dbref.child("names");
    namesref.on("value", function(snapshot) {
        snapshot.forEach(i => {
            if(i.key == user_id && i.child("realname").val() == user_realname) {
                return true;
            }
        });
    });
    return false;
}

但是,无论输入如何,它最初都会 return 为假。我认为这是因为它会在加载 firebase 数据时转到 "return false"。

因此,即使最终 return 为真,由于第一次 return 值为假,它会导致这样的问题(在另一个函数中)。

function name_match2() {
    var user_id = document.getElementById("user-id").value;
    var user_realname = document.getElementById("user-realname").value;
    if(!name_match(user_id, user_realname)) return -1;
    return 0;
}

它会 return -1.

你能解释一下如何解决这个问题吗?

正如丹尼尔在评论中所解释的那样,外部函数永远不会 returns 为真。异步解决方案可能是这些 :)

function name_match(user_id, user_realname) {
    return new Promise(function (resolve, reject) {
      var dbref = firebase.database().ref();
      var namesref = dbref.child("names");
      namesref.on("value", function(snapshot) {
          var matched = false;
          snapshot.forEach(i => {
              if(i.key == user_id && i.child("realname").val() == user_realname) {
                  matched = true;
              }
          });

          if (matched) {
             resolve()
          } else {
             reject()
          }
      });
    });
}

在调用函数的另一边

name_match('userId', 'userName').then(function(){
//matched
}, function(){
//unmatched
}); 

其他方法是使用回调:

function name_match(user_id, user_realname, cb) {
      var dbref = firebase.database().ref();
      var namesref = dbref.child("names");
      namesref.on("value", function(snapshot) {
          var matched = false;
          snapshot.forEach(i => {
              if(i.key == user_id && i.child("realname").val() == user_realname) {
                  matched = true;
              }
          });

          cb(matched);
    });
}

在这种情况下:

name_match('userId', 'userName', function(matched) {
    console.log(matched);
})

这里是 Suryapratap 解决方案的一个小改编,使用 once() 方法,

  1. "Listens for exactly one event of the specified event type, and then stops listening.",以及
  2. Returns一个承诺

... 而不是使用设置侦听器的 on() 方法。

function name_match(user_id, user_realname) {

      var dbref = firebase.database().ref();
      var namesref = dbref.child("names");

      return namesref.once('value').then(function(snapshot) {
          var matched = false;
          snapshot.forEach(i => {
              if(i.key == user_id && i.child("realname").val() == user_realname) {
                  matched = true;
              }
          });
          return matched;
      });

}