I have an interval running every 6 seconds on my page; it populates a bunch of data really nicely.
However, there is one piece of data that is only updated from the DB every 30 seconds. So, I want to wait to execute this callback because if it executes beforehand, it wipes everything out.
My code below waits 30 seconds and then checks. What I'd like is the opposite: Check immediately and then wait 30 seconds before checking again.
I feel like my code is cloogy below and there's a much more elegant solution (though I don't think a do/while loop fits the bill). Am I wrong?
counter = 0;
maxCounts = 5;
function callbackForInterval(){
if(counter === maxCounts){
if({data hasn't changed}){
// wipe everything out!!!
}else{
// do some other stuff
}
counter = 0;
}
counter++;
}
Thanks for any helpful hints.
You can use the remainder operator (%).
var counter = 0;
function callbackForInterval)( {
if (counter++ % 5 === 0) {
// This bit only runs every 5 iterations
}
}
That will run the code on the first iteration. To run it only starting with the 5th, change the post-increment to a pre-increment.
Live Example:
var counter = 0;
function callbackForInterval() {
if (counter++ % 5 === 0) {
snippet.log("big tick");
// This bit only runs every 5 iterations
} else {
snippet.log("little tick");
}
}
var timer = setInterval(callbackForInterval, 500);
setTimeout(function() {
snippet.log("done");
clearInterval(timer);
}, 30000);
snippet.log("(stops after 30 seconds)");
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Side note: I added var to the above, because unless you're declaring that counter variable somewhere, your code is falling prey to The Horror of Implicit Globals.
Related
This time go faster if is called 2 times, 3 times faster and so on.
function startIdleTime() {
var ciclo;
function startSlidercicle() {
ciclo = setInterval( function() {
let seconds = parseInt(sessionStorage.getItem('idle'));
seconds += 1;
sessionStorage.setItem('idle', seconds);
}, 1000);
}
// start idle counter
if (!sessionStorage.getItem('idle')) {
alert('non esiste timer, lo imposto')
sessionStorage.setItem('idle', 0);
alert(3)
}
if (sessionStorage.getItem('idle') > 15) {
anotherFunction();
}
if (sessionStorage.getItem('idle') < 15 || !sessionStorage.getItem('idle')) {
clearInterval(ciclo);
startSlidercicle();
}
}
I need to set idle time. When 15 i'll call an other function,
if <= 15 I reset only a counter to 0
But if is called few times my count go faster then 1sec }, 1000);)
Looks like the interval is not cleared before instantiating a new one. The result will be several intervals that will be executed with a different phase, and it will look like it's running with a shorter interval.
The reason for this behavior is that you are not clearing the interval, because you are creating a new ciclo variable every time you call the startIdleTime function. Probably you want the variable ciclo to be global, in order to share the interval handler across the function calls. You need to widen the scope, and to widen the scope you can just move the variable declaration out of the function definition:
var ciclo;
function startIdleTime() {
function startSlidercicle() {
Also note that in the following line:
sessionStorage.getItem('idle') < 15 || !sessionStorage.getItem('idle')
the second part is never evaluated. Let's suppose that getItem returns null: then null < 15 is true, so the check becomes useless
I can't figure out why setTimeout is being called multiple times in my code.
Here's a snippet of the code with what I thought was irrelevant removed:
let dead;
setup()
{
dead = false;
}
draw()
{
if(fell == true)
{
dead = true;
}
mechanics();
}
function mechanics()
{
let triggerVar;
if(dead == true)
{
triggerVar = 1;
dead = false;
}
if(triggerVar == 1)
{
setTimeout(resetG, 1500);
triggerVar = 0;
}
}
function resetG()
{
lives -= 1;
position = 0;
}
I can't tell what I'm doing wrong because whenever the character dies and setTimeout is called, it is actually not only called after the delay but also for the exact same duration after it is triggered. So in this case it is triggered first after 1500 millis and then every frame for another 1500 millis.
I managed to find the problem, which was not with the code I posted. The problem was that the constructor code that makes the object that changes dead to true if certain conditions are met was being called every frame from the moment it triggered death until the first instance of setTimeout kicked in, which means setTimeout was called every frame for 1500 milliseconds.
Chances are that you mechanics() function is called multiple times, you may give a variable to the settimeout like:
let timeoutID= setTimeout(resetG, 1500);
And in the proper place to clear it, for example after lifecycle
clearTimeout(timeoutID);
My setTimeout statements are making function calls instantly instead of waiting the time I specified and I'm not sure why. It should take 10 seconds for the for loop and then 110 seconds to change a boolean value from T to F.
for(var c = 0; c < 10; c++)
{
setTimeout(function()
{
gold = gold + clickerPower;
$("#totalGold").html("Gold: " + gold);
console.log("Clicked!");
}, 1000);
}
setTimeout(function(){frenzyActive = false;}, 110000);
Starting a timeout is an asynchronous operation. setTimeout accepts a function as it's first argument because it's registering that callback function to be invoked at a later time. Every iteration of the JavaScript event loop it checks to see if the appropriate time has passed and if so then it fires the registered callback. Meanwhile it's still moving on to run other code while it waits.
Your for loop is not waiting for anything. It iterates to 10 super fast and all you've done is register ten callbacks to fire all at the same time in exactly one second (the time is specified in milliseconds by the way, so 1000 = 1 second).
You need setInterval.
var count = 0;
var intervalId = setInterval(function () {
gold = gold + clickerPower;
$('#totalGold').html('Gold: ' + gold);
console.log('Clicked!');
count++;
if (count === 10) {
clearInterval(intervalId);
frenzyActive = false;
}
}, 1000);
That function will run once every second and increment a count variable each time. When it reaches 10 we call clearInterval and give it the intervalId returned from setInterval. This will stop the interval from continuing.
Take a gander at this post I wrote back when I too was confused about asynchronous callbacks :)
http://codetunnel.io/what-are-callbacks-and-promises/
I hope that helps :)
Good luck!
It will not take 10 seconds to execute the loop. Look will execute immediately and the anonymous function will be enqueued 10 times to be executed after 1 second.
The last call to setTimeout will cause the anonymous function to be executed after 110 seconds.
To ensure that the anonymous function within the loop is called sequentially, 10 times, after a gap of 1 second each, do the following:
var c = 0;
setTimeout(function() {
if(c < 10) {
gold = gold + clickPower;
console.log("Clicked");
c++;
setTimeout(arguments.callee, 1000);
//^^ Schedule yourself to be called after 1 second
}
}, 1000);
I did come across this challenge today, and the answer provided by #Guarav Vaish set me on a path to success. In my case, I am using ES6 syntax and its worth noting that the arguments.callee is deprecated. However, here is how I'd write the same solution as contributed by Vaish:
var c = 0;
setTimeout(function named() {
if(c < 10) {
gold = gold + clickPower;
console.log("Clicked");
c++;
setTimeout( ()=>{ named() }, 1000);
//^^ Schedule yourself to be called after 1 second
}
}, 1000);
Note: I am simply using a named function in place of the anonymous one in the original solution. Thank you. This was really helpful
Learning about callbacks and the solution to this problem eludes me.
It should print a number every second counting down until zero. Currently, it logs the numbers from 10 - 0 but all at once and continues in an infinite loop.
Please help me to gain a better understanding of this situation. I have read up on callbacks and have a conceptual understanding but execution is still a bit tricky.
var seconds = 0;
var countDown = function(){
for(var cnt = 10; cnt > 0; cnt--){
setTimeout(function(x){
return function(){
seconds++
console.log(x);
};
}(cnt), seconds * 1000);
}
}
countDown()
The way your code is working now, it executes a for loop with cnt going from 10 to 1. This works. On each iteration, it schedules a new function to be run in seconds * 1000 milliseconds, carefully and properly isolating the value of cnt in x each time. The problem is that seconds is 0, and it will only be changed once a callback executes; but by the time a callback executes, all of them will already have been scheduled for execution. If you need seconds * 1000 to vary while you’re still scheduling them all (while the for loop is still running), you need to change seconds in the loop, rather than inside one of the callbacks.
Read up on IIFEs to see how they work. In this situation, you're creating a closure of the value you want to print. You had the right idea, but your syntax was off.
var seconds = 0;
var countDown = function () {
var cnt = 10;
// simplify your loop
while (cnt--) {
// setTimeout expects a function
// use an IIFE to capture the current value to log
setTimeout((function (x) {
// return the function that setTimeout will execute
return function (){
console.log(x + 1);
};
}(cnt)), (++seconds) * 1000);
}
};
countDown();
I'm learning Javascript, I read about scope and variables but can't get information about how to send variables between the functions.
Please can someone to explain how to be with this situation and it would be great to recommend something to read about it.
I want to draw a picture 30 times with 30 different parameters, and get the last parameter for checking function:
function loadImg{
.....
img.onload = function() { // Loading first picture at the start
........
boo.onclick = function() { // the function which by click start all process
var i = 0;
var num; // the variable which I'm going to use for random numbers.
setInterval(function() {
// here I'm generating random numbers
num = Math.floor(Math.random() * imgs.length);
// and then start draw() function, which is going to get the 'num' parameter and draw a pictures with time interval ONLY 30 times
if(i < 30){
draw(num);
i++; }, 2000);
check(num); // after all, I want to run "check()" function which is going to get THE LAST from that 30 generated 'num' parameter and check some information. But is undefined, because it's outside the setInterval function and I don't wont to put it in, because it will starts again and again.
How to get the last parameter for check(num) function?
P.S. Sorry for my english I've been trying to describe as good a as I can.
You could call check(num) inside the setInterval() function with a condition:
if(i < 30){
draw(num);
i++;
}
else
{
check(num);
}
You should also then end your loop as this will keep running indefinitely.
To do this assign the interval to a variable:
var myInterval = setInterval(function() {
And then clear the interval before calling check():
if(i < 30){
draw(num);
i++;
}
else
{
clearInterval(myInterval);
check(num);
}