Meteor 1.6:在另一个流星方法调用启动的服务器上清除超时

时间:2018-01-23 15:11:57

标签: meteor

我正在使用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由于数据更改而在一秒内多次更新并显示闪烁。

1 个答案:

答案 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;
    }
});

这种方法不是持久的,但并非必须如此,因为在服务器启动后所有定时器都已重置,信息就是针。尽管如此,请记住另一个示例(使用集合),因为它是一种经常出现的模式,当您需要持久支持信息时。