我正在使用Meteor 1.6.0.1 用例是客户端每5秒调用一次meteor方法告诉服务器它是在线的,服务器存储最后的事件时间,在线收集。
Meteor.methods({
'ping.online'() {
MyColl.update({_id:this.userId}, {$set:{last_online:Date.now(), online:true}})
}
});
如果在1分钟之前没有活动,我还想离线标记。为此,我想到了以下方式。
Meteor.methods({
'ping.online'() {
MyColl.update({_id:this.userId}, {$set:{last_online:Date.now(), online:true}});
let timer = Meteor.setTimeout(()=>{
MyColl.update({_id:this.userId}, {$set:{online:false}});
}, 60*1000)
}
});
为了实现这个目的,我必须在5秒后下一次ping时调用Meteor.clearTimeout(timer)
。我很困惑如何存储计时器值并在同一客户端/用户的下一次调用中使用它。
我可以只存储last_online时间并使用相同的逻辑将其显示为脱机,但是当我将其发布到客户端时,客户端会收到太多更新,因为每个用户都会对此字段进行频繁更改。这导致ui由于数据更改而在一秒内多次更新并显示闪烁。
答案 0 :(得分:1)
一般说明:Meteor有一些软件包可以自动且高效地解决用户在线状态。仍然发布以下代码,以支持对通过使用第二个"支持"来跟踪某个字段的方法的一般理解。集合。
编辑:在我发现之后,Meteor.setTimeout返回一个句柄而不是一个id我必须重写我的解决方案。更新版本位于底部。
一种可行的方法是使用键/值模式创建名为Timers
的第二个集合:
{
timerId:String,
userId:String,
}
通过这样做,您可以将当前计时器存储在此集合的文档中。如果方法运行中存在timerDoc,则可以通过存储的计时器ID清除计时器:
Meteor.methods({
'ping.online'() {
// get timer, if present
// and clear timeout
const timerDoc = Timers.findOne({userId:this.userId})
if (timerDoc && timerDoc.timerId) {
Meteor.clearTimeout(timerDoc.timerId);
}
// update collection
MyColl.update({_id:this.userId}, {$set:{last_online:Date.now(), online:true}});
// create new timer
let timer = Meteor.setTimeout(()=>{
MyColl.update({_id:this.userId}, {$set:{online:false}});
Timers.remove({_id: timerDoc._id});
}, 60*1000);
// update Timers collection
if (timerDoc) {
Timers.update({_id: timerDoc._id}, {$set: {timerId: timer} });
}else{
Timers.insert({
timerId: timer,
userId: this.userId,
});
}
}
});
上面的代码不适用于Meteor.setTimeout
,因为它不会返回计时器ID,而是返回句柄as described in the docs。
您可以使用普通对象缓存计时器对象,该对象充当字典。
但是,这并不妨碍您缓存计时器句柄并以与上述代码类似的方式使用它。
// your timers dictionary
const Timers = {};
Meteor.methods({
'ping.online'() {
// get timer, if present
// and clear timeout
const existingTimer = Timers[this.userId];
if (existingTimer) {
Meteor.clearTimeout(existingTimer.timerId);
delete Timers[this.userId];
}
// update collection
MyColl.update({_id:this.userId}, {$set:{last_online:Date.now(), online:true}});
// create new timer
let timerHandle = Meteor.setTimeout(()=>{
MyColl.update({_id:this.userId}, {$set:{online:false}});
delete Timers[this.userId];
}, 60*1000);
// store timerHandle in dictionary
Timers[this.userId] = timerHandle;
}
});
这种方法不是持久的,但并非必须如此,因为在服务器启动后所有定时器都已重置,信息就是针。尽管如此,请记住另一个示例(使用集合),因为它是一种经常出现的模式,当您需要持久支持信息时。