Javascript 检查用户是否在Firebase中联机
我在Google Firebase文档中找到了一个我需要的示例 尽管如此,我还是想对其进行一些修改,使其每秒钟/10秒或至少每分钟检查一次用户的存在情况,这取决于这将如何影响服务器上的负载,因此我提出了以下建议: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
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);
}
}