Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/440.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 检查用户是否在Firebase中联机_Javascript_Firebase_Firebase Realtime Database - Fatal编程技术网

Javascript 检查用户是否在Firebase中联机

Javascript 检查用户是否在Firebase中联机,javascript,firebase,firebase-realtime-database,Javascript,Firebase,Firebase Realtime Database,我在Google Firebase文档中找到了一个我需要的示例 尽管如此,我还是想对其进行一些修改,使其每秒钟/10秒或至少每分钟检查一次用户的存在情况,这取决于这将如何影响服务器上的负载,因此我提出了以下建议: TestApp.prototype.initFirebase = function() { this.database = firebase.database(); this.database.ref(".info/connected").on("value", thi

我在Google Firebase文档中找到了一个我需要的示例

尽管如此,我还是想对其进行一些修改,使其每秒钟/10秒或至少每分钟检查一次用户的存在情况,这取决于这将如何影响服务器上的负载,因此我提出了以下建议:

TestApp.prototype.initFirebase = function() {
    this.database = firebase.database();
    this.database.ref(".info/connected").on("value", this.isOnline.bind(this));
};

TestApp.prototype.isOnline = function(snap) {
    var i=0;
    console.log(snap.val());
    setInterval(function() {
        if (snap.val() === true) {
            console.log("connected"+(i+=10));
        } else {
            console.log("not connected");
        }
    }, 10000);
}
但如果我运行控制台,控制台中会发生以下情况:

它每10秒触发一次该功能,但同时向我显示
已连接
已断开
的两个结果。(实际上,大约有1秒的延迟)此外,它完全忽略用户是否登录,每次都向我显示相同的日志

我希望它仅在用户登录(使用电子邮件和密码)时运行
isOnline
方法。如果这是真的,
isOnline
应该在用户每N秒在线时向服务器发送请求。有什么我能做的吗


如果我可以检查用户是否从服务器端连接,这会更好,因为只要用户保持在线,我就需要执行一些操作。但我不确定这是否可行,所以我认为最好的方法是检查前端并使用HTTP触发器触发操作

当前行为是由于计时器闭包中捕获了
snap
的值

当您将
isOnline
设置为触发
value
事件时,Firebase会在每次键的值更改时调用该方法。在这种情况下,Firebase在确定值为
false
时第一次调用
isOnline
,然后在建立登录后第二次调用,该值变为
true

现在在
isOnline
中,您开始超时。由于使用不同的
snap
对象调用函数两次,因此创建了两个超时。但它们在闭包中都有自己的
snap
对象,这些对象在调用
isOnline
时固定为值

最终的结果是,您有两个永久计时器在运行,它们一直在打印历史
snap
值:)

正如您提到的,只有当且仅当用户在线时,您才希望定期执行某些操作,您应该尝试以下方法:

isOnline : function(snap){
  let test = snap.val();
  // If the user is not online,
  // check if we had the timer set,
  // as we should clear it now.
  // It essentially means user went offline.
  if (!test && this.whenOnline) {
    clearTimeout(this.whenOnline);
    this.whenOnline = null;
    return;
  }

  // If the user is not online, return.
  if (!test){
    return;
  }

  // User is online. Install the timer if we haven't.
  if (!this.whenOnline){
    this.whenOnline = setTimeout(this.doSomethingWhenOnline, 10000);
  }
}

doSomethingWhenOnline : function(){
  // whatever;

  // Cue the next timer again, notice we only install if
  // the previous instance has not been cleared by the
  // isOnline handler.
  if (this.whenOnline){
    this.whenOnline = setTimeout(this.doSomethingWhenOnline, 10000);
  }
}

谢谢回复!现在我还有一个问题<代码>设置超时不循环该功能,控制台中只显示一条消息。老问题仍然存在:即使用户没有登录他的帐户,DoSomethingHenonline也会触发。所以我有几个问题:为什么我不使用以前实际工作的
setInterval
,以及如何修复这个未经授权的触发?我在这里留下了更多的代码,也许这会有帮助(也许
onAuthStateChanged
会破坏整个过程,或者什么?):我的意思是你说这个方法被调用了两次,但我不明白为什么。可能是因为连接状态只有在用户实际连接到服务器之后才会改变。但是,为什么在建立连接后,它每次都在
间隔中输出“false”?最后,如何在这里包括用户身份验证?我的意思是,我不应该只检查用户是否在线,我还想检查用户是否拥有一个帐户并使用该帐户登录,以实际连续为他生成一些积分。
isOnline
被fb调用两次,因为db引用的值最初从零变为“false”,然后变为“true”。您不应该使用
setInterval
,因为如果第一个调用正在等待ajax返回,那么它可能会导致重入。对于执行服务器操作的回调,您应该更喜欢
setTimeout
。就像我在代码中所做的那样,您总是可以从当前调用链接下一个调用。我建议开始一次如此的聊天,因为在评论中不可能回答个别问题:)。只是我不知道如何开始聊天。大多数情况下,当我们交换了一些评论时会出现这种情况。如果您总是想评估用户是否已连接,您可以更改策略,使用一个简单的计时器,在每次调用中,使用
this.database.ref(“.info/connected”)。一次(“value”,this.isOnline.bind(this))。请注意,我正在使用
一次
来确保isOnline只被调用一次。这将保证您在isOnline中获得最新的快照。我不知道我是否有足够的声誉开始聊天。您说您的示例运行良好,但它没有使用那些
setTimeOut
循环函数。我误解了什么吗?因为我看到它只完成了一次我的功能,就这样。我觉得这里有点不对劲。
isOnline : function(snap){
  let test = snap.val();
  // If the user is not online,
  // check if we had the timer set,
  // as we should clear it now.
  // It essentially means user went offline.
  if (!test && this.whenOnline) {
    clearTimeout(this.whenOnline);
    this.whenOnline = null;
    return;
  }

  // If the user is not online, return.
  if (!test){
    return;
  }

  // User is online. Install the timer if we haven't.
  if (!this.whenOnline){
    this.whenOnline = setTimeout(this.doSomethingWhenOnline, 10000);
  }
}

doSomethingWhenOnline : function(){
  // whatever;

  // Cue the next timer again, notice we only install if
  // the previous instance has not been cleared by the
  // isOnline handler.
  if (this.whenOnline){
    this.whenOnline = setTimeout(this.doSomethingWhenOnline, 10000);
  }
}