我在Google Firebase文档here中找到了我需要的示例。
仍然,我想稍微修改它,使其每秒/ 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);
}
但是如果我运行它,控制台中会发生什么:
main.js:34 false main.js:91 User signed out main.js:34 true main.js:39 not connected main.js:37 connected10 main.js:39 not connected main.js:37 connected20 main.js:39 not connected main.js:37 connected30 main.js:39 not connected main.js:37 connected40
它每隔10秒触发一次该功能,但它同时显示connected
和disconnected
两个结果。 (实际上,延迟大约1秒)此外,如果用户登录或不登录,它会完全忽略,并且每次都显示相同的日志。
我希望它仅在用户登录时使用isOnline
方法(使用电子邮件和密码)。如果确实如此isOnline
如果用户每隔N秒在线,则应向服务器发送请求。有什么我能做的吗?
如果我可以检查用户是否从服务器端连接会好得多,因为只要用户保持在线,我就需要做一些操作。但我不确定这是否可能,所以我认为最好的办法是检查前端并触发HTTP触发器的操作。
答案 0 :(得分:1)
当前行为是由于在计时器闭包中捕获snap
的值。
当您设置isOnline
以触发value
事件时,Firebase会在每次密钥值更改时调用该方法。在这种情况下,Firebase在确定值为isOnline
时首次调用false
,然后在登录成功后第二次调用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);
}
}