首页 文章

使用Meteor的服务器端setInterval / clearInterval

提问于
浏览
4

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

运行 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}});

    }
});

另外,您会注意到在play方法中,我在 setInterval 函数内设置了 intervalId . 我绝望地尝试了这个,它起作用了 . 出于某种原因,如果我在使用 Entries.update({_id: currentPlayTimer._id},{$set:{intervalId: IntervalId}}) 创建间隔计时器后立即尝试更新文档,则会失败 .

所有这些都很适合作为客户端代码,但我需要在服务器端完成 . 我希望计时器能够以正确的速度继续运行,无论您是在5台设备上打开页面还是没有打开页面 .

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

1 回答

  • 6

    这主要归结为两个问题:首先, setIntervalclearInterval 的实现在客户端(至少在Chrome中)和Node中是不同的,其次是you can't serialise functions in BSON,这意味着所有方法和包含方法的属性都是当您尝试将其作为文档插入服务器时从对象中删除 . 's why the object you subsequently retrieve is so much simpler/smaller, and why you can' t将其传递给 clearInterval ,因为它缺少大部分所需信息 .

    如果你在客户端中记录 setInterval 的返回值,那么'll notice that it'只是一个整数,当然可以被序列化,所以你得到的东西与MongoDB完全相同,并且 clearInterval 工作正常 . 我在 set...clearInterval 的客户端实现上根本不是专家,但坦率地说,确定了一个四位数的整数 .

    总而言之,我不能按照您在服务器上尝试的方式进行操作,除非其他人能够想到一种智能的方法来序列化清除它所需的 interval 对象的一部分并且一旦检索到它就重建一个合适的对象,但这需要比我拥有的Node更多的知识 . 否则,我认为你有两个选择:

    • 只需将您的间隔存储在某种类型的vanilla javascript对象的内存中 .

    • 使用备用对象进行计时,以便存储可序列化的标识符 . 我过去曾使用过meteor-cron软件包,虽然很简单,但是可能值得一看,看看是否可以使用该软件包或其衍 生产环境 品 .

相关问题