I'm creating a Meteor app that has some simple timers in it. Pressing the start or stop buttons on a timer each call a method to set or clear an interval timer, among other things. When I setInterval
, I store the resulting object in the current timer document so that it is easy to find later when I want to clear the interval timer. This is where I'm running into issues.
When running Meteor.setInterval()
server-side, it returns an object. According to the node.js docs, this is normal. If I log the resulting object after creation, it returns this:
{ _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 }
If I log the object after retrieving it from my document, I get this:
{ _idleTimeout: 5000,
_idlePrev: null,
_idleNext: null,
_idleStart: 1393271968144,
_repeat: true }
So, using clearInterval
with this does not work. Here is my server-side code:
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}});
}
});
Also, you will notice that in the play method, I set intervalId
inside of the setInterval
function. I tried this in desperation, and it worked. For some reason, if I try to update the document right after creating the interval timer with Entries.update({_id: currentPlayTimer._id},{$set:{intervalId: IntervalId}})
, it fails.
All of this worked great as client-side code, but I need this to be done server side. I want the timer to keep going at the correct pace whether you have the page open on 5 devices or none.
Thanks for your help! This project is my first using Meteor or anything on Node, and I am really enjoying it so far.
It's worth noting that the pool of IDs used by setInterval() and setTimeout() are shared, which means you can technically use clearInterval() and clearTimeout() interchangeably.
The setInterval() function is commonly used to set a delay for functions that are executed again and again, such as animations. You can cancel the interval using clearInterval() . If you wish to have your function called once after the specified delay, use setTimeout() .
The clearInterval() method clears a timer set with the setInterval() method.
The setInterval method has the same syntax as setTimeout : let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...)
This is essentially down to two issues: firstly, that the implementations of setInterval
and clearInterval
are different on the client (at least in Chrome) and in Node, and secondly that you can't serialise functions in BSON, which means that all your methods, and properties containing methods, are being dropped from the object when you try to insert it as a document on the server. That's why the object you subsequently retrieve is so much simpler/smaller, and why you can't pass it to clearInterval
, as it's missing most of the required information.
If you log the return value of setInterval
in the client, you'll notice that it's just an integer, which can of course be serialised, and so you get exactly the same thing out of the MongoDB as you put in, and clearInterval
works fine. I am no expert at all on the client implementation of set...
and clearInterval
, but frankly a four-digit integer doesn't seem particularly robust for this purpose, although it does have some advantages that you've identified.
In summary, I don't think you're going to be able to go about things the way in which you're attempting on the server, unless somebody else can think of a smart way of serialising the part of the interval
object which is required for clearing it and rebuilding an appropriate object once it's been retrieved, but this requires more knowledge of Node than I possess. Otherwise, I think you have two options:
meteor-cron
package in the past, albeit briefly, and it may be worth a look to see if this is possible using that package or some derivative thereof.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With