I was planning to get a data from the server every minute. However, if I run this code, this function is being called repeatedly. On the other hand, if I added date.getMilliseconds == 0 in the condition, it won't process any results.
Do you have any suggestions on how to run the function once every 1 minute?
async update() {
var date = new Date();
if (date.getSeconds() == 0) {
var newdata = await getData(1);
array.shift();
array.push(newdata);
}
}
Since it looks like you don't have fine control over when update is called, one option would be to set a boolean to true every time getSeconds() === 0 (set it to false otherwise), and then only run the real code when the flag is false and getSeconds() === 0:
let hasRun = false;
// ...
async update() {
var date = new Date();
const secs = date.getSeconds();
if (secs !== 0) {
hasRun = false;
} else if (secs === 0 && hasRun === false) {
hasRun = true;
// your code
var newdata = await getData(1);
array.shift();
array.push(newdata);
}
}
An alternative that might require less resources due to not creating Dates every frame would be to have a separate function that toggles the boolean, set with a setInterval that runs every 60 seconds, no Dates involved:
let hasRun = false;
setInterval(() => hasRun = false, 60000);
async update() {
if (hasRun) return;
hasRun = true;
// your code
}
(of course, you could also try setInterval(update, 60000) if the framework allows it)
Related
Creating a function onceEvery(), that allows a function to be called only once every x milliseconds. The first result is able to return, but the function doesn't stop it from being recalled before cooldown time is completed, returning the previous result instead. Thanks in advance!
onceEvery = function (func, wait) {
//return function then can only return every * seconds
let cooldown = false;
let result;
let previous;
//if called again while cooldown = true, return previous result
if (!cooldown) {
result = func;
previous = result;
beginCoolDown();
return result;
} else {
return previous;
}
function beginCoolDown () {
cooldown = true;
setTimeout (function () {
cooldown = false;
}, wait);
}
}
You do this by keeping track of the last result you provided and when you last provided it, outside the function, and then using that when the function is called to decide whether to update that information:
const minInterval = 5000; // 5 seconds (for example)
let lastResult = null; // Last result provided
let nextAvailable = Date.now(); // When the next can be provided
function onceEvery() {
const now = Date.now();
if (now < nextAvailable) {
return lastResult;
}
lastResult = /*...calculate result...*/;
nextAvailable = now + minInterval;
return lastResult;
}
Live Example:
const minInterval = 5000; // 5 seconds (for example)
let lastResult = null; // Last result provided
let nextAvailable = Date.now(); // When the next can be provided
function onceEvery() {
const now = Date.now();
if (now < nextAvailable) {
console.log(Date.now(), "Too soon, returning last value:", lastResult);
return lastResult;
}
lastResult = (lastResult || 0) + 1;
nextAvailable = now + minInterval;
console.log(Date.now(), "Calculated new value:", lastResult);
return lastResult;
}
// Call it every second or so
setInterval(onceEvery, 1000);
You can use the concept of JavaScript closures. Return a wrapped function which executes only after waiting wait period.
To do this, maintain a flag isCalled on the outer function, which is initially false so that the function can be called immediately.
Once called the isCalled is set to true so that on next invocations the function has to wait until the timer executes and resets it to false:
function onceEvery(func, wait) {
let isCalled = false;
let result;
return () => {
//if not called call the func
if (!isCalled) {
result = func();
//set to true
isCalled = true;
setTimeout(() => {
//reset after waiting wait period
isCalled = false;
}, wait);
}
//return computed value
//returns old value until new value is computed
return result;
}
}
let func = onceEvery(() => Date.now(), 2000);
setInterval(() => {
console.log(func());
}, 400)
You have to define function beginCoolDown() outside of the onceEvery(), and move the definition of the cooldown outside of the function.
That would be look like this:
let cooldown = false
function beginCoolDown() {
...
}
function onceEvery() {
...
}
I'm trying to display a second countdown after the first one finishes. I'm using meteor. This is the timer:
sec = 5
#timer = setInterval((->
$('#timer').text sec--
if sec == -1
$('#timer').fadeOut 'fast'
sec=
timer
return
), 1000)
This is how I call it
When the template is rendered I call a setTimeout and a countdown displays
Template.selector.rendered = ->
window.setTimeout(startGame, 5000)
timer
When game starts I need a second countdown. I managed it like this:
sec = 5
sw = 0
#timer = setInterval((->
$('#timer').text sec--
if sec == -1
if sw == 0
sw = 1
sec = 20
else if sw == 1
clearInterval timer
return
), 1000)
But there has to be a better way.
If you plan to use many timers, you could make an object to achieve that. Here is an example taken from here You could adapt it to your case using custom events:
ReactiveTimer = (function () {
// Constructor
function ReactiveTimer(interval) {
this._dependency = new Tracker.Dependency;
this._intervalId = null;
if(_.isFinite(interval))
this.start(interval);
};
ReactiveTimer.prototype.start = function(interval){
var _this = this;
this._intervalId = Meteor.setInterval(function(){
// rerun every "interval"
_this._dependency.changed();
}, 1000 * interval);
};
ReactiveTimer.prototype.stop = function(){
Meteor.clearInterval(this._intervalId);
this._intervalId = null;
};
ReactiveTimer.prototype.tick = function(){
this._dependency.depend();
};
return ReactiveTimer;
})();
<div id="counter">1:00</div>
function countdown() {
var secs = 60;
function tick() {
var counter = document.getElementById("counter");
secs--;
counter.innerHTML = "0:" + (secs < 10 ? "0" : "") + String(secs);
if( secs > 0 ) {
setTimeout(tick, 1000);
} else {
alert("Game Over");
}
}
tick();
}
countdown(60);
I am having a problem with this portion of my game. I'm trying to set a 60 seconds timer for the game that starts at 60 and ends at 0, when it gets to 0 the game stops and an alert shows that the game is over.
I am very new to programming, so please give me as many feedbacks as you can. I found this code on the internet, and I figured out most of it, could you also tell me what does the tick() function do over here?
Here is one way you can do it:
First declare a variable you will use for an interval (should be 'global', attached to window):
var countDownInterval = null;
Then, a function to trigger the tick interval, you should call this whenever the game is ready to start:
function startCountDown()
{
countDownInterval = setInterval(tick,1000); //sets an interval with a pointer to the tick function, called every 1000ms
}
which will call the tick function every second:
function tick()
{
// Check to see if the counter has been initialized
if ( typeof countDownInterval.counter == 'undefined' )
{
// It has not... perform the initialization
countDownInterval.counter = 0; //or 60 and countdown to 0
}
else
{
countDownInterval.counter++; //or --
}
console.log(countDownInterval.counter); //You can always check out your count # the log console.
//Update your html/css/images/anything you need to do, e.g. show the count.
if(60<= countDownInterval.counter) //if limit has been reached
{
stopGame(); //function which will clear the interval and do whatever else you need to do.
}
}
and then the function where you can do everything you need to do after game has finished:
function stopGame()
{
clearInterval(countDownInterval);//Stops the interval
//Then do anything else you want to do, call game over functions, etc.
}
You can fire up the counter at any time by calling startCountDown();
Pseudo code of tick:
function tick() {
reduce counter variable;
if counter > 0
wait for 1 second; (This is what setTimeout(tick, 1000) means)
call tick() again (recursively)
}
else {
game over
}
}
Something like this?
var countdown = function(sec, tick, done) {
var interval = setInterval(function(){
if(sec <= 0) {
clearInterval(interval);
done();
} else {
tick(sec)
sec--;
}
}, 1000)
}
countdown(10, console.log, function(){console.log('done')})
This question already has an answer here:
How to disable a button with a timed loop?
(1 answer)
Closed 9 years ago.
Attack = attack button.
When I run this code (click on the button), it takes about 1 second to disable the button. How can I set this up to disable instantly? I'm assuming it's because of the 1000 ms timer, but i'm not sure.
var disabledStartTimer = setInterval(disabledTimer, 1000);
var start = 0;
function disabledTimer() {
if (start > 5){
clearInterval(disabledStartTimer);
console.log("disabled timer stopped");
blitz.disabled = false;
}
else {
blitz.disabled = true;
start++;
};
}
yes, it's because of the 1000ms timer. if you set it to 10 it will take 10 ms to disable. if you need it to start disabled, move (or copy) the blitz.disabled = true code out of the interval callback:
var disabledStartTimer = setInterval(disabledTimer, 1000);
var start = 1; // set to 1 to maintain consistency (i.e. call blitz.disabled = true the same amount of times as the original code.
blitz.disabled = true;
function disabledTimer() {
if (start > 5) {
clearInterval(disabledStartTimer);
console.log("disabled timer stopped");
blitz.disabled = false;
}
else {
blitz.disabled = true;
start++;
}
}
if you need to do more complex stuff and this code is just an example, you can wrap your complex statements inside a function and call it from outside and inside the interval:
var disabledStartTimer = setInterval(disabledTimer, 1000);
var start = 1; // set to 1 to maintain consistency (i.e. call blitz.disabled = true the same amount of times as the original code.
function disableBlitz() {
blitz.disabled = true;
}
disableBlitz();
function disabledTimer() {
if (start > 5) {
clearInterval(disabledStartTimer);
console.log("disabled timer stopped");
blitz.disabled = false;
}
else {
disableBlitz();
start++;
}
}
set the timer to 0
var disabledStartTimer = setInterval(disabledTimer, 0);
or simply call
disabledTimer();
Set this:
var disabledStartTimer = setInterval(disabledTimer, 1000); // 1 sec
To this:
var disabledStartTimer = setInterval(disabledTimer, 0); // 0 sec
As the time is counted here in Milliseconds. You can be sure of this, it really is because of the setInterval.
Simple question here that I can't seem to find an answer for: Once a setTimeout is set, is there any way to see if it's still, well, set?
if (!Timer)
{
Timer = setTimeout(DoThis,60000);
}
From what I can tell, when you clearTimeout, the variable remains at its last value. A console.log I just looked at shows Timer as being '12', no matter if the timeout has been set or cleared. Do I have to null out the variable as well, or use some other variable as a boolean saying, yes, I have set this timer? Surely there's a way to just check to see if the timeout is still running... right? I don't need to know how long is left, just if it's still running.
What I do is:
var timer = null;
if (timer != null) {
window.clearTimeout(timer);
timer = null;
}
else {
timer = window.setTimeout(yourFunction, 0);
}
There isn't anyway to interact with the timer except to start it or stop it. I typically null the timer variable in the timeout handler rather than use a flag to indicate that the timer isn't running. There's a nice description on W3Schools about how the timer works. In their example they use a flag variable.
The value you are seeing is a handle to the current timer, which is used when you clear (stop) it.
There is no need to check for an existing timer, just execute clearTimeout before starting the timer.
var timer;
//..
var startTimer = function() {
clearTimeout(timer);
timer = setTimeout(DoThis, 6000);
}
This will clear any timer before starting a new instance.
Set another variable Timer_Started = true with your timer. And also change the variable to false when the timer function is called:
// set 'Timer_Started' when you setTimeout
var Timer_Started = true;
var Timer = setTimeout(DoThis,60000);
function DoThis(){
// function DoThis actions
//note that timer is done.
Timer_Started = false;
}
function Check_If_My_Timer_Is_Done(){
if(Timer_Started){
alert("The timer must still be running.");
}else{
alert("The timer is DONE.");
}
}
I know this is a necroposting but i think still people are looking for this.
This is what i use:
3 variables:
t for milliseconds since.. in Date Object for next target
timerSys for the actual interval
seconds threshold for milliseconds has been set
next i have a function timer with 1 variable the function checks if variable is truly, if so he check if timer is already running and if this is the case than fills the global vars , if not truly, falsely, clears the interval and set global var timerSys to false;
var t, timerSys, seconds;
function timer(s) {
if (s && typeof s === "number") {
if (typeof timerSys === "boolean" || typeof timerSys === "undefined") {
timerSys = setInterval(function() {
sys();
}, s);
t = new Date().setMilliseconds(s);
seconds = s;
}
} else {
clearInterval(timerSys);
timerSys = false;
}
return ((!timerSys) ? "0" : t)
}
function sys() {
t = new Date().setMilliseconds(seconds);
}
Example I
Now you can add a line to sys function:
function sys() {
t = new Date().setMilliseconds(seconds);
console.log("Next execution: " + new Date(t));
//this is also the place where you put functions & code needed to happen when interval is triggerd
}
And execute :
timer(5000);
Every 5 seconds in console:
//output:: Next execution: Sun May 08 2016 11:01:05 GMT+0200 (Romance (zomertijd))
Example II
function sys() {
t = new Date().setMilliseconds(seconds);
console.log("Next execution: " + seconds/1000 + " seconds");
}
$(function() {
timer(5000);
});
Every 5 seconds in console:
//output:: Next execution: 5 seconds
Example III
var t, timerSys, seconds;
function timer(s) {
if (s && typeof s === "number") {
if (typeof timerSys === "boolean" || typeof timerSys === "undefined") {
timerSys = setInterval(function() {
sys();
}, s);
t = new Date().setMilliseconds(s);
seconds = s;
}
} else {
clearInterval(timerSys);
timerSys = false;
}
return ((!timerSys) ? "0" : t)
}
function sys() {
t = new Date().setMilliseconds(seconds);
console.log("Next execution: " + seconds / 1000 + " seconds");
}
$(function() {
timer(5000);
$("button").on("click", function() {
$("span").text(t - new Date());
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Freebeer</button>
<span></span>
Note this way you can go below 0
I usually nullify the timer:
var alarm = setTimeout(wakeUpOneHourLater, 3600000);
function wakeUpOneHourLater() {
alarm = null; //stop alarm after sleeping for exactly one hour
}
//...
if (!alarm) {
console.log('Oops, waked up too early...Zzz...');
}
else {
console.log('Slept for at least one hour!');
}