// Adapted from: https://github.com/remcoder/chronos (MIT License) import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import { ReactiveVar } from 'meteor/reactive-var'; import moment from 'moment'; const _timers = {}; function Timer(interval) { this.interval = interval || 1000; this.time = new ReactiveVar(0); } Timer.prototype.start = function () { if (this._timer) throw new Error('Trying to start Chronos.Timer but it is already running.'); this.time.set(new Date()); this._timer = setInterval(Meteor.bindEnvironment(() => { // console.log('tick', this._timer); this.time.set(new Date()); }), this.interval); }; Timer.prototype.stop = function () { // console.log('stopping timer'); clearInterval(this._timer); this._timer = null; }; function _update(interval) { // get current reactive context const comp = Tracker.currentComputation; if (!comp) { return; } // no nothing when used outside a reactive context // only create one timer per reactive context to prevent stacking of timers const cid = comp && comp._id; if (!_timers[cid]) { const timer = new Timer(interval); _timers[cid] = timer; // add destroy method that stops the timer and removes itself from the list timer.destroy = function () { timer.stop(); delete _timers[cid]; }; timer.start(); } // make sure to stop and delete the attached timer when the computation is stopped comp.onInvalidate(() => { // console.log('onInvalidated',comp); if (comp.stopped && _timers[cid]) { // console.log('computation stopped'); _timers[cid].destroy(); } }); _timers[cid].time.dep.depend(comp); // make dependent on time // console.log(_timers); return _timers[cid]; } // reactive version of moment() // please install moment separately // example usage: Chronos.moment(someTimestamp).format('ss'); function _moment(/* arguments */) { if (!moment) throw new Error('moment not found. Please install it first'); _update(); return moment(...arguments); } // reactive version of new Date() get the current date/time function _date(interval) { _update(interval); return new Date(); } // reactive version of Date.now(). get the current # of milliseconds since the start of the epoch function _now(interval) { _update(interval); return Date.now(); } // export global const Chronos = { // a simple reactive timer // usage: var timer = new Timer(); // get current time: timer.time.get(); Timer, // handy util func for making reactive contexts live updating in time // usage: simply call Chronos.update() in your helper to make it execute // every interval update: _update, // reactive version of new Date() get the current date/time date: _date, // reactive version of Date.now(). get the current # of milliseconds since the start of the epoch now: _now, // reactive version of moment() // please install moment separately // example usage: Chronos.moment(someTimestamp).format('ss'); moment: _moment, // for debugging and testing _timers, // deprecated. but kept for backwards compatibility liveUpdate: _update, currentTime: _date, liveMoment: _moment }; export default Chronos;