I am trying to "cache" some information by storing it in a variable.
If 2 minutes have passed I want to get the "live" values (call the url).
If 2 minutes have not passed I want to get the data from the variable.
What I basicly want is:
if(time passed is less than 2 minutes) {
get from variable
} else {
get from url
set the time (for checking if 2 minutes have passed)
}
I've tried calculating the time with things like
if((currentime + 2) < futuretime)
but it wouldn't work for me.
Anybody know how to properly check if 2 minutes have passed since the last executing of the code?
TL;DR: Want to check if 2 minutes have passed with an IF statement.
Turning your algorithm into working javascript, you could do something like this:
var lastTime = 0;
if ( Math.floor((new Date() - lastTime)/60000) < 2 ) {
// get from variable
} else {
// get from url
lastTime = new Date();
}
You could put the if block in a function, and call it anytime you want to get the info from either the variable or the url:
var lastTime = 0;
function getInfo() {
if ( Math.floor((new Date() - lastTime)/60000) < 2 ) {
// get from variable
} else {
// get from url
lastTime = new Date();
}
}
Hope it helps.
If you want to do something on a timer in JavaScript, you should be using setTimeout or setInterval.
Having your code run in a continuous loop will cause your browser's VM to crash.
Using setTimeout is rather easy:
setTimeout(function(){
// do everything you want to do
}, 1000*60*2);
This will cause the function to run in at least two minutes from the time the timeout is set(see this blog post from John Resig for more deatils). The second argument is the number of milliseconds, so we multiply by 60 to get minutes, and then 2 to get 2 minutes.
setInterval, which follows the same syntax will do something EVERY x milliseconds.
Without using 3rd party libs, just use Date.getTime() and store it as some variable:
var lastRun = null;
function oneIn2Min() {
if (lastRun == null || new Date().getTime() - lastRun > 2000) {
console.log('executed');
}
lastRun = new Date().getTime();
}
oneIn2Min(); // prints 'executed'
oneIn2Min(); // does nothing
oneIn2Min(); // does nothing
setTimeout(oneIn2Min, 2500); // prints 'executed'
You can also opt to make some simple object out of it (to keep your code organised). It could look like this:
var CachedCall = function (minTime, cbk) {
this.cbk = cbk;
this.minTime = minTime;
};
CachedCall.prototype = {
lastRun: null,
invoke: function () {
if (this.lastRun == null || new Date().getTime() - this.lastRun > this.minTime) {
this.cbk();
}
this.lastRun = new Date().getTime();
}
};
// CachedCall which will invoke function if last invocation
// was at least 2000 msec ago
var c = new CachedCall(2000, function () {
console.log('executed');
});
c.invoke(); // prints 'executed'
c.invoke(); // prints nothing
c.invoke(); // prints nothing
setTimeout(function () {c.invoke();}, 2300); // prints 'executed'
If you're open to include 3rd party libs this might be very handy in other tasks too:
http://momentjs.com/docs/#/manipulating/add/
You can do something like that
var myVal = {
data: null,
time: new Date()
}
function getMyVal () {
if(myVal.time < new Date(new Date().getTime() - minutes*1000*60)) {
myVal.data = valFromRequest;
myVal=time=new Date();
}
return myVal.data;
}
Related
Code :
class Schedule extends Component {
state = {
new_date: null
}
componentDidMount() {
var start = new Date().getMinutes()
var end = 24
var diff = end - start
var interval = setInterval(() => {
this.setState({
new_date: new Date()
})
}, diff)
interval()
}
}
Here all i want is to pass different timer value on each page refresh or specific condition is satisfied
Suppose when i refresh the page i will have new date and i want to subtract new date from end and here i can get suppose diff == 5000 millisecond.
But the problem is after the timer has executed i want to again find new date in the variable start and substract it from variable end so that i will have different value in variable diff and thus different timer value and above code cannot update the value of variable start.
It would be great help if somebody could help me out
You should clear interval if you want to change the time
let interval
class Schedule extends Component {
runInterval: (time) => {
if (interval) {
clearInterval(interval)
interval = null
}
interval = setInterval(() => {
// do something in here and you have also a new time
// pass new time to run interval function to have interval with new
// time
this.runInterval(3000) // 3000 is an example of a new time
}, intervalPeriod)
}
componentDidMount() {
var start = new Date().getMinutes()
var end = 24
var diff = end - start
this.runInterval(diff)
}
}
you need to use setTimeout and in this timeout call again setTimeout with different time value
var time = 1000;
function recursion(){
time = 2000;
setTimeout(function(){
recursion();
},time);
}
recursion();
I'm quite a newbie, so forgive my ignorance. I am trying to, through local storage, get a timer to tell the user when they last visited the page. But I have instead made an infinite loop, how do I correct this? calling the function outside the function? What would this look like?
$(document).ready(function(){
var myDate = new Date(2015,4,9,0,0);
localStorage["mydate"] = JSON.stringify(myDate);
startTimer();
});
function startTimer() {
setInterval(function(){
var text = "It's been " + hoursSinceFirstVisit() + " hours since you first visited.";
$('#timer').text(text);
}, 1000);
}
function hoursSinceFirstVisit() {
var currentDate = new Date();
var lastDate = new Date(JSON.parse(localStorage["mydate"]));
return hoursBetweenDates( lastDate, currentDate);
}
<div id="timer"></div>
Thanks!
There is no hoursBetweenDates function provided, so I added one. For debugging recursion errors, try moving the anonymous function to a named function as it is called repeatedly. Break code into smaller parts and make sure no part repeatedly calls itself:
$(document).ready(function() {
var myDate = new Date(2015, 4, 9, 0, 0);
localStorage.mydate = JSON.stringify(myDate);
function startTimer() {
setInterval(updateMessage, 100);
}
function updateMessage() {
var text = "It's been " + hoursSinceFirstVisit() + " hours since you first visited.";
$('#timer').text(text);
}
// This is my function for getting hours between dates
function hoursBetweenDates(d1, d2) {
return Math.abs(d1 - d2) / 36e5;
// For integer hours use this function
// return Math.floor(Math.abs(d1 - d2) / 36e5);
}
function hoursSinceFirstVisit() {
var currentDate = new Date();
var lastDate = new Date(JSON.parse(localStorage.mydate));
return hoursBetweenDates(lastDate, currentDate);
}
startTimer();
});
This will work fine without recursion errors. Here is a demo. Note, I made it return hours with decimal precision since the last visit, and set the interval to 100 ms to demonstrate it works fine. Update your version as you like. Apologies, I could not make a Stack Snippet because local storage is disabled.
Demo: http://jsbin.com/demevi/3/
The function setInterval() schedules a function to be executed repeatedly, waiting a specified number of milliseconds before each run.
If you want to delay the execution of function hoursSinceFirstVisit() (and run it only once) then you have to use setTimeout():
function startTimer() {
setTimeout(function() {
var text = "It's been " + hoursSinceFirstVisit() + " hours since you first visited.";
$('#timer').text(text);
}, 1000);
}
I have a game in which two people play against each other. After the clock runs down I call the function below, which is supposed to increase the current question by 1. However, it increases it by 1 TWICE.
increaseQuestion: function() {
GameCollection.update({current:true}, { $inc: { currentQuestion: 1}});
},
Here is specifically the code where it is called:
Template.gamePage.clock = function () {
var game = GameCollection.findOne({current: true});
var currentQuestion = game.currentQuestion;
var question = game.gameQuestions[currentQuestion];
var clockQuestion = Clocks.findOne({gameId: game._id, questionId: question._id});
var clock = clockQuestion.clock;
if(clock === 0) {
Meteor.call('increaseQuestion');
} else {
Meteor.call('windDown', clockQuestion, clock);
}
// format into M:SS
var min = Math.floor(clock / 60);
var sec = clock % 60;
return min + ':' + (sec < 10 ? ('0' + sec) : sec);
};
Here is the method within the code above (which could be causing problems)
Meteor.methods({
windDown: function(clockQuestion, clock) {
var interval = Meteor.setInterval(function () {
clock -= 1;
Clocks.update(clockQuestion._id, {$set: {clock: clock}});
// end of game
if (clock === 0) {
// stop the clock
Meteor.clearInterval(interval);
// declare zero or more winners
}
}, 1000);
}
});
Why is the function being called twice? I tried moving the method from both client and server folder to a server only folder and it is still called twice.
I'm surprised it's only being called twice, to be honest.
The clock helper has a dependency on the ClockQuestion document which has the same gameId as the current game. However, when that helper is run, the windDown method is called, which is going to update that ClockQuestion document, which is going to cause the helper to be reactively rerun, which is going to call the windDown method again, etc...
To be honest, this sort of control logic really should not be included in a helper function for exactly this reason - it's going to be impossible to control. windDown needs to be called by whatever it is that's making the gamePage template render in the first place, or else a Deps.autorun block, the reactivity of which you can have much more control over, as opposed to a reactive UI element which is (by design) being managed by Meteor rather than your own app explicitly.
My suspicion is this: Template.gamePage.clock uses GameCollection, so when that collection is updated, then the function will be re-run reactively.
Since increaseQuestion doesn't depend on any arguments from the client, why not just move it to the // end of game if block in windDown?
I want to detect a change in the value of Date().getSeconds() as soon as it happens.
I currently use:
function updateClock {
....
}
function detectChange(previousSec) {
var currentSec = new Date().getSeconds();
if (previousSec !== currentSec) {
updateClock();
}
}
setInterval(function () {
var dat = new Date();
var sec = dat.getSeconds;
detectChange(sec);
}, 10);
Is there a better way to do this?
Thanks!
How about a 2-step process?
First, align your clock with the system's 0-millisecond mark
setTimeout(startClock, 1000 - (new Date()).getMilliseconds());
Then, you only need to tick once per second
function startClock() {
setInterval(function do_your_thing() { ... }, 1000);
}
Practical demonstration (jsfiddle) shows that even if you do a large amount of work during the cycle, this method is pretty stable. In fact, on my machine you get better precision than the ±16ms resolution typically achievable in desktop task schedulers.
Unfortunately there is no standard event that fires when the clock changes seconds, so you'll need to set up an interval to detect it.
Setting an interval for every 1000ms means your clock could be off by almost a full second. Therefore I can understand why you'd want to check the seconds more than just once per second. The core concept here is sampling rate. The faster we sample the more precise we are, but the more processing time we waste detecting changes.
I think this will work for you.
function updateClock (date) {
console.log(date);
};
(function () {
var oldDate = new Date();
return setInterval(function () {
var date = new Date();
if (date.getSeconds() != oldDate.getSeconds()) {
updateClock(date);
}
oldDate = date;
}, 10); // precision is ~10ms
})();
It will have a new value after every one second, therefore just put a timer with 1 second interval.
I have a simple countdown plugin which counts down second by second to a time, and upon reaching that time it runs a callback function of my choosing.
What I have discovered today is that if I have two countdowns on the same page, and one countdown finishes, a javascript error occurs because a variable becomes undefined, which also breaks the second countdown.
Here's the code:
(function($) {
$.fn.countdown = function(options, callback) {
var $self = $(this);
var settings = {
'date' : null,
}
if(options) {
$.extend(settings, options);
}
function countdownProcessor() {
var eventDate = Date.parse(settings.date) / 1000;
var currentDate = Math.floor($.now() / 1000);
if (eventDate <= currentDate) {
callback.call(this);
clearInterval(interval);
}
var secondsBetween = eventDate - currentDate;
// processing logic here.
}
countdownProcessor();
interval = setInterval(countdownProcessor, 1000);
}
})(jQuery);
The issue is with the if statement which checks to make sure the date has not already occurred:
if (eventDate <= currentDate) {
callback.call(this);
clearInterval(interval);
}
When this condition becomes true, the callback completes successfully, but clearInterval does not because the variable interval is not defined - this is because the countdown function is run before interval is declared.
I've tried fixing it by switching the interval variable declaration and countdownProcessor(); around, but this doesn't help because it simply causes the first, ended countdown to count into the negatives.
I've a few other methods like changing the scope and order of declaration of some of the code, but it invariably leads to the countdown either A) counting into the negatives, or B) still erroring out.
How can I fix this?
Add var:
var interval = setInterval(countdownProcessor,1000);
This makes the interval local to each countdown that is being run, rather than global to the entire page.