2014-02-24 109 views
4

我正在创建一个Meteor应用程序,它有一些简单的计时器。按下定时器上的开始或停止按钮,每个调用一种方法来设置或清除间隔定时器等等。当我setInterval时,我将结果对象存储在当前的定时器文档中,以便稍后当我想要清除间隔计时器时很容易找到。这是我遇到问题的地方。服务器端setInterval/clearInterval与流星

当运行Meteor.setInterval()服务器端时,它返回一个对象。根据node.js文档,这是正常的。如果我日志创建后生成的对象,它返回:

{ _idleTimeout: 5000, 
    _idlePrev: 
    { _idleNext: [Circular], 
    _idlePrev: 
     { _idleTimeout: 5000, 
     _idlePrev: [Object], 
     _idleNext: [Circular], 
     _idleStart: 1393271941639, 
     _onTimeout: [Function], 
     _repeat: false }, 
    msecs: 5000, 
    ontimeout: [Function: listOnTimeout] }, 
    _idleNext: 
    { _idleTimeout: 5000, 
    _idlePrev: [Circular], 
    _idleNext: 
     { _idleTimeout: 5000, 
     _idlePrev: [Circular], 
     _idleNext: [Object], 
     _idleStart: 1393271941639, 
     _onTimeout: [Function], 
     _repeat: false }, 
    _idleStart: 1393271941639, 
    _onTimeout: [Function], 
    _repeat: false }, 
    _idleStart: 1393271943127, 
    _onTimeout: [Function: wrapper], 
    _repeat: true } 

如果我从我的文档检索它后登录的对象,我得到这个:

{ _idleTimeout: 5000, 
    _idlePrev: null, 
    _idleNext: null, 
    _idleStart: 1393271968144, 
    _repeat: true } 

因此,使用clearInterval与此不不行。这里是我的服务器端代码:

Meteor.methods({ 

    play: function(entry){ //entry is the document 
     var currentPlayTimer = entry; //Global variable for the interval timer 
     Entries.update({_id: currentPlayTimer._id},{$set:{playing:true}}); //This is mostly to set the status of the play button for the client 
     var IntervalId = Meteor.setInterval(function(){Entries.update({_id: currentPlayTimer._id},{$inc:{time:1},$set:{intervalId: IntervalId}});},5000); //Increment by 1 every 5 seconds, put the object from the interval timer into the current document 
     console.log(IntervalId); 
    }, 

    stop: function(entry){ //entry is the document 
     var currentPlayTimer = entry; 
     IntervalId = currentPlayTimer.intervalId; 
     console.log(IntervalId); 
     Meteor.clearInterval(IntervalId); 
     Entries.update({_id: currentPlayTimer._id},{$set:{playing:false, intervalId: null}}); 

    } 
}); 

而且,你会发现,在剧中方法,我设置intervalIdsetInterval函数内。我在绝望中尝试了这一点,并且工作。出于某种原因,如果我尝试在创建间隔计时器Entries.update({_id: currentPlayTimer._id},{$set:{intervalId: IntervalId}})后立即更新文档,则会失败。

所有这些工作都非常适合客户端代码,但我需要在服务器端完成此操作。我希望计时器能够保持正确的速度,无论您的网页是在5台设备上打开还是不打开。

感谢您的帮助!这个项目是我第一次使用Meteor或Node上的任何东西,到目前为止我非常喜欢它。

回答

6

这本质上是下降到两个问题:首先,中setIntervalclearInterval的实现是客户端(至少在铬)上的不同和节点,其次是you can't serialise functions in BSON,这意味着所有的方法是,和属性包含方法,当您尝试将其作为文档插入服务器时,将从对象中删除。这就是为什么你随后检索的对象变得更简单/更小,以及为什么你不能将它传递给clearInterval,因为它缺少大部分所需的信息。

如果您在客户端中记录返回值setInterval,您会注意到它只是一个整数,当然这个整数可以被序列化,所以您可以像MongoDB一样从MongoDB中获得完全相同的结果,和clearInterval工作正常。我在set...clearInterval的客户端实现方面并不是专家,但坦率地说,一个四位数的整数对于这个目的看起来并不特别有效,尽管它确实有一些你已经确定的优点。

总的来说,我认为你不可能在服务器上尝试你想要的事情,除非别人能想到一个聪明的方式来串行化部分interval清除它并重建适当对象一旦被检索到的对象,但这需要更多的Node知识。否则,我认为你有两种选择:

  • 只需将你的区间存储在某种香草javascript对象的内存中。
  • 使用替代对象进行计时,这将允许您存储可序列化的标识符。过去我已经使用了meteor-cron软件包,虽然简单一些,可能值得一看,看看是否可以使用该软件包或其衍生产品。
+2

谢谢!这就说得通了。这是我为此问题的任何其他人所做的: 创建一个数组以保存'setInterval'对象 'var intervalArray = [];' 将对象('IntervalId')推入数组中,存储位置。这只是一个数字,所以我可以将它存储在MongoDB文档中。 'intervalArrayPosition = intervalArray.push(IntervalId) - 1;' 后来,读的位置退了出来,并明确如下: 'Meteor.clearInterval(intervalArray [intervalArrayPosition]);' – dotbat

+0

我想要做类似的事情,即使用户关闭了浏览器,服务器上的“setInterval”也应该保持运行,直到他们登录并停止它为止 - 因此,与想要保存到数据库相同的问题。注销后'var intervalArray = []'如何保持? – evolross