Changing MS of setInterval depending on a condition - javascript

I'm trying to change the speed at which my program will iterate through my array and put info into my text area. But I don't think I understand the functionality of setInterval and setTimeout perfectly, or maybe its something else, I'm very new to JS.
var theStage,getDrop,getSize,time,isChecked,turbo;
function changeFrame(stopper){
if(isChecked === true){
turbo = 50;
}
else{
turbo = 250;
}
time = setInterval(start, turbo);
}
function start(){
var frames = theStage.value.split("=====\n");
var i = 0, l = frames.length;
(function iterator() {
theStage.value = frames[i];
if(++i<l) {
setTimeout(iterator, turbo);
}
})();
};

setTimeout and setInterval are creating a new timer each time you call them. If you want to have one timer, but change how often it's executed, then you need to remove it and "set" with a new time, like this:
var timer = null;
...
// Each time, before creating a new timer, remove the old one.
if (timer !== null)
clearInterval(timer)
timer = setInterval(...);
I think, that your code can be simplified to use only one timer:
var theStage, isChecked, delay;
var frames = theStage.value.split("=====\n");
var progress = 0, l = frames.length;
function changeSpeed() {
if (isChecked)
delay = 50;
else
delay = 250;
}
function processFrame() {
theStage.value = frames[progress];
if (++progress < l)
// Recursively call self until whole list of frames is processed.
setTimeout(processFrame, delay);
}
When you use setTimeout to create recursive function then you don't need to reset timer.

Related

infinitetly loop array with setTimeout javascript

I have an array of strings that I'm passing to a for loop with a setTimeout inside.
I've tried to for(; ;) and while(true) the function but this just causes the browser to crash.
I've also tried adding an if statement inside the function
if (x == links.length) { loopUrls() }
Which works kind of but skips the entire interval section of the function, cycling the entire array infinitely with no wait.
function loopUrls() {
for (var x = 0, ln = links.length; x < ln; x++) {
setTimeout(function (y) {
document.getElementById('ifURLS').src = links[y];
},x * 500,x);
}
};
loopUrls();
The aim is to have a list of urls that infinitely assigned to the iframe to show reports on a sreen. (the time interval is just small for testing purposes)
There is no need to have multiple timeouts. You can achieve this using setInterval which executes a function every x amount of time. Then in that funciton you keep a state of the current url so you can show the next time the function is run
// creates a function that iterates over the array and every time its called returns the next element
function createIterator(array){
let sourceArray = [...array];
// starts at the end so it resets automatically
let topIndex = sourceArray.length;
let currentIndex = topIndex - 1;
return function (){
currentIndex++;
// if the limit is reached, its reseated
if (currentIndex === topIndex) {
currentIndex = 0;
}
return sourceArray[currentIndex];
}
}
// your urls
let urls = ["a", "b", "c"];
// uses the function to create the iterator
let iterator = createIterator(urls);
setInterval(function() {
let currentUrl = iterator();
document.getElementById('ifURLS').src = currentUrl;
},1000);
No need for loops, as the iterator handles seamlessly
If I understand correctly, you want for every link to have some function that is being executed every X milliseconds.
In order to achieve this I think it's better to use setInterval.
You can do something like:
links.forEach((link) => {
setInterval(() => {
//do something every X milliseconds
}, X)
})
a way to do that :
// const links = [ ... ]
const myImg = document.queryselector('#ifURLS')
function LoadImg()
{
let
indx = 0
, let refIntv =
setInterval( ()=>
{
myImg.src = links[indx++]
if (indx >= links.length)
clearInterval( refIntv )
}
, 5000 ) // 5s delay
}

need help fixing a countdown clock with javascript

I am trying to create a countdown clock and have hit a bit of a snag. It is displaying the final number, the final result of the for loop, which I don't want. My goal is to have to for loop fire my .setTimeout every time it loops. I would appreciate any help.
const countdownClock = (ranNum) => {
const startingNum = ranNum * 50;
for(let i = startingNum; i > 0; i--) {
setTimeout(() => countdownSpan.textContent = [i], 1000);
}
}
That's because of the setTimeout is waiting for 1s to execute and until then the loop is completed even before your first setTimeout triggers and when your first timeout is triggered the value of i is updated and is now the last number of the loop. You can handle it with the promises and async/await.
const countdownClock = async (ranNum) => {
const startingNum = ranNum * 50;
for(let i = startingNum; i > 0; i--) {
await new Promise(resolve => {
setTimeout(() => {
countdownSpan.textContent = [i];
resolve()
}, 1000)
});
}
}
Hope it helps!
Timer functions won't fire until after the current function is complete. This is why your for loop runs to completion before the timer function runs. In order to see the timer tick away, you shouldn't use a loop at all because the timer will create the looping functionality. You only need either a setInterval() or a setTimeout() that is recursive.
const element = document.getElementById("countdown");
let startingNum = parseInt(Math.random() * 50, 10);
let timer = null;
function counter(){
// Clear any running timer to prevent multiple
// timers from stacking up in the event queue
clearTimeout(timer);
startingNum--; // Decrease the counter
// If the count is greater than 0
if(startingNum >-1){
element.textContent = startingNum;
// Set a new timer up to call this function
timer = setTimeout(counter, 1000);
}
}
// Start the process off
timer = setTimeout(counter, 1000);
<div id="countdown"></div>

Javascript function, need to decrement every 30 secs time elapsed

I'm trying to make the this.SPAWN_FREQUENCY decrease by 200 after time elapsed reaches 30 seconds, 1 min, 2 min and so on. Basically levels in the game increasing the amount of enemies to defeat. I've tried a load of code and still can't get anything to work.
Any suggestions where to start?
Sorry if I didn't provide enough detail.
function EnemyManager (timer) {
this.enemies = [];
this.SPEED = -5;
this.SPAWN_FREQUENCY = 1300;
this.spawnTimer = 0;
Do I add 'if' statement?
Use setTimeout
(function () {
var interval = 1000*30;
var SPAWN_FREQUENCY = 1300;
timer = function() {
SPAWN_FREQUENCY = SPAWN_FREQUENCY - 200;
//do the rest
console.log(SPAWN_FREQUENCY);
setTimeout(timer, interval);
interval = interval*2;
};
timer();
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
have you tried something like:
function Manager(){
this.SPAWN_FREQUENCY = 1300;
this.inc();
}
Manager.prototype.inc = function(){
var this_store = this;
setTimeout(function(){
this_store.SPAWN_FREQUENCY -= 200;
this_store.inc();
}, 100);
};
Your function:
var element = this;
var spawninterval = window.setInterval(function(){
element.SPAWN_FREQUENCY -= 200;
},30000);
and when you're done, you can call
window.clearInterval(spawninterval);

Using clearTimeout with multiple instances of setTimeout

I'm creating an 'advanced' Tic Tac Toe game in which each turn disappears after 10 seconds (ie: each X or O placed reverts to a blank square after 10 seconds). This all works fine, but the issue arises if a user decides to cancel the current game and start a new one.
If a user starts a new game and clicks on a square that was previously occupied, the timeout function will clear that square in accordance with the click from the previous game -- ie, in less than 10 seconds.
Using clearTimeout resets the timer for the most recent instance of SetTimeout, but doesn't help if there were multiple squares selected when the user reset the game board. And because setTimeout is applied to each X and O in an onclick function, I don't have a way to track multiple instance IDs.
Any thoughts would be much appreciated, code below.
EDIT: You can see a live version of the game (WIP) here: http://kylechadha.com/projects/tic-tac-toe/
Global variables:
var elements = document.getElementsByClassName('cell');
var rows = document.getElementsByClassName('row');
var alternate = 0;
var counter = 0;
var timerX; // Handles setTimeout instances for 'X'
var timerO; // Handles setTimeout instances for 'O'
Function to set X's and O's:
var play = function() {
for (i = 0; i < elements.length; i++) {
elements[i].onclick = function () {
if (this.className[0] == "c" && win == false) {
if (alternate % 2 == 0) {
this.className = "xmove";
alternate++;
counter++;
var paramPass = this;
timerX = setTimeout(function() {disappear(paramPass);}, 10000) // Handles ID of most recent instance of setTimeout for 'X'
} else {
this.className = "omove";
alternate++;
counter++;
var paramPass = this;
timerO = setTimeout(function() {disappear(paramPass);}, 10000) // Handles ID of most recent instance of setTimeout for 'O'
}
}
position(this);
analysis();
}
}
}
Reset function when user clicks 'New Game':
var reset = function() {
header[0].innerHTML = "Tic Tac Toe";
for (i = 0; i < rows.length; i++) {
for (j = 1; j < 6; j += 2) {
rows[i].childNodes[j].className = "cell animated bounceIn";
}
}
clearTimeout(timerX); // Clears Timeout for most recent instance (last 'X' clicked) before the game was reset
clearTimeout(timerO); // Clears Timeout for most recent instance (last 'O' clicked) before the game was reset
board = [["","",""],["","",""],["","",""]];
counter = 0;
alternate = 0;
win = false;
}
Keep a list of pending timeouts. Each timeout removes itself from the list when it triggers. When you reset, iterate over the list and clearTimeout on each.
Something like this:
var pending = {};
function mySetTimeout(callback, delay) {
var t;
t = setTimeout(function() {delete pending[t];callback()}, delay)
pending[t]=1;
}
function clearAllTimeouts() {
for (var t in pending) if (pending.hasOwnProperty(t)) {
clearTimeout(t);
delete pending[t];
}
}
The easiest solution would be to create an array of timer IDs and then whenever you want to clear them, iterate through the array with a for loop and use clearTimeout on each. You can use Array.push to add IDs to the timer array.

How to create pause or delay in FOR loop?

I am working on a website, where I need to create a pause or delay.
So please tell me How to create pause or delay in for loop in javascript or jQuery
This is a test example
var s = document.getElementById("div1");
for (i = 0; i < 10; i++) {
s.innerHTML = s.innerHTML + i.toString();
//create a pause of 2 seconds.
}
You can't use a delay in the function, because then the change that you do to the element would not show up until you exit the function.
Use the setTimeout to run pieces of code at a later time:
var s = document.getElementById("div1");
for (i = 0; i < 10; i++) {
// create a closure to preserve the value of "i"
(function(i){
window.setTimeout(function(){
s.innerHTML = s.innerHTML + i.toString();
}, i * 2000);
}(i));
}
var wonderfulFunction = function(i) {
var s = document.getElementById("div1"); //you could pass this element as a parameter as well
i = i || 0;
if(i < 10) {
s.innerHTML = s.innerHTML + i.toString();
i++;
//create a pause of 2 seconds.
setTimeout(function() { wonderfulFunction(i) }, 2000);
}
}
//first call
wonderfulFunction(); //or wonderfulFunction(0);
You can't pause javascript code, the whole language is made to work with events, the solution I provided let's you execute the function with some delay, but the execution never stops.
I tried all one, but I think this code is better one, it is very simple code.
var s = document.getElementById("div1");
var i = 0;
setInterval(function () {s.innerHTML = s.innerHTML + i.toString(); i++;}, 2000);
if you want to create pause or delay in FOR loop,the only real method is
while (true) {
if( new Date()-startTime >= 2000) {
break;
}
}
the startTime is the time before you run the while
but this method will cause the browsers become very slow
It is impossible to directly pause a Javascript function within a for loop then later resume at that point.
This is how you should do it
var i = 0;
setTimeout(function() {
s.innerHTML = s.innerHTML + i.toString();
i++;
},2000);
The following code is an example of pseudo-multithreading that you can do in JS, it's roughly an example of how you can delay each iteration of a loop:
var counter = 0;
// A single iteration of your loop
// log the current value of counter as an example
// then wait before doing the next iteration
function printCounter() {
console.log(counter);
counter++;
if (counter < 10)
setTimeout(printCounter, 1000);
}
// Start the loop
printCounter();
While several of the other answers would work, I find the code to be less elegant. The Frame.js library was designed to solve this problem exactly. Using Frame you could do it like this:
var s = document.getElementById("div1");
for (i = 0; i < 10; i++) {
Frame(2000, function(callback){ // each iteration would pause by 2 secs
s.innerHTML = s.innerHTML + i.toString();
callback();
});
}
Frame.start();
In this case, it is nearly the same as the examples that use setTimeout, but Frame offers a lot of advantages, especially if the you are trying to do multiple or nested timeouts, or have a larger JS application that the timeouts need to work within.
I am executing a function where I need access to the outside object properties. So, the closure in Guffa solution doesn't work for me. I found a variation of nicosantangelo solution by simply wrapping the setTimeout in an if statement so it doesn't run forever.
var i = 0;
function test(){
rootObj.arrayOfObj[i].someFunction();
i++;
if( i < rootObj.arrayOfObj.length ){
setTimeout(test, 50 ); //50ms delay
}
}
test();
The way I found was to simply use setInterval() to loop instead. Here's my code example :
var i = 0;
var inte = setInterval(() => {
doSomething();
if (i == 9) clearInterval(inte);
i++;
}, 1000);
function doSomething() {
console.log(i);
};
This loops from 0 to 9 waiting 1 second in between each iteration.
Output :
0 1 2 3 4 5 6 7 8 9
It is not possible to pause a loop. However you can delay the execution of code fragments with the setTimeout() function. It would not make a lot of sense to pause the entire execution anyway.
I am using while loop and check the pause variable to check the user pause/resume the code.
var pause = false;
(async () => {
for (let index = 0; index < 1000; index++) {
while (pause) {
await new Promise((res) => setTimeout(res, 1000));
console.log("waiting");
}
await new Promise((res) => setTimeout(res, 1000));
console.log(index);
}
})();
const pausefunc = async () => {
pause = true;
};
const playfunc = () => {
pause = false;
};
<button onclick="playfunc()">Play</button>
<button onclick="pausefunc()">Pause</button>
I used a do...while loop to put a delay in my code for a modal dialog that was closing too quickly.
your stuff....
var tNow = Date.now();
var dateDiff = 0;
do {
dateDiff = Date.now() - tNow;
} while (dateDiff < 1000); //milliseconds - 2000 = 2 seconds
your stuff....

Categories

Resources