I am trying to achieve a situation when a function inside setTimeout is executed after X seconds first time, and then regularly at Y interval.
useEffect(() => {
let firstTime = true;
const timer = setTimeout(() => {
getValue(id).then((res) => {
setValue(res);
});
if (firstTime) {
firstTime = false;
}
}, firstTime ? 30000 : 60000);
return () => clearTimeout(timer);
}, [])
This doesn't work, however, as it sets firstTime to false before running the function. Is there a way to graciously achieve the result? Is it even possible with setTimeout?
You can use a variable as the setTimeout delay. In this case you would set firstTime to the delay you wanted to use the first time (30000), and then inside timer you would use if (firstTime == 30000) { firstTime = 60000; }. Using a different variable name here would make sense. Then set the setTimeout delay to just firstTime like }, firstTime);
Hopefully this is actually what you wanted.
useEffect(() => {
let firstTime = 30000;
const timer = setTimeout(() => {
getValue(id).then((res) => {
setValue(res);
});
if (firstTime == 30000) {
firstTime = 60000;
}
}, firstTime);
return () => clearTimeout(timer);
}, [])
Old (incorrect) answer:
You can use setTimeout with an initial delay to initialise a setInterval, which will repeat subsequent times at a different interval.
Related
So I'm making a timer in html and javascript and I am displaying it on a button. I want to make it so that when the value of time is equal to zero, it alerts the user. Here is my code so far. btw, the code is part of the timer code.
const time2=
document.getElementById("countdown")
if(time2==0:00)
alert("You have ran out of time, better luck next time!")
You can create a timer with a setInterval() and trigger some functionality when a value is reached, in this case the timer is cleared, i hope this helps:
const createTimer = (num) => {
const timer = setInterval(() => {
console.log(num)
num--;
if(num == 0) {
console.log("You have ran out of time, better luck next time!")
clearInterval(timer)
}
}, 1000)
}
createTimer(4)
something like this?
let div = document.getElementById('count')
let countdown = 10
let stopper = setInterval(myTimer, 1000)
function myTimer() {
countdown--
div.innerHTML = countdown + " seconds left"
if (countdown == 0) {
clearInterval(stopper)
}
}
<div id='count'>10 seconds left</div>
Here is one possible implementation of a very simple Timer using a class. Most important is setInterval() which will allow you to run a function every x milliseconds.
This timer uses a callback function onUpdate(seconds) which is called every time the timer is updated and provides the remaining seconds as a parameter. You could certainly extend on that.
It is also required to wait for the HMTL document to have loaded before trying to access the DOM using the DOMContentLoaded event.
class Timer {
#interval;
#initial;
#seconds;
constructor(seconds, onUpdate) {
this.#initial = seconds;
this.#seconds = seconds;
this.onUpdate = onUpdate;
this.onUpdate(seconds);
}
start() {
this.#interval = setInterval(() => {
this.#seconds--;
if (this.#seconds === 0) this.stop();
this.onUpdate(this.#seconds);
}, 1000);
}
reset() {
this.stop();
this.#seconds = this.#initial;
this.onUpdate(this.#seconds);
}
stop() {
clearInterval(this.#interval);
this.onUpdate(this.#seconds);
}
}
// wait for HTML document to load
window.addEventListener("DOMContentLoaded", e => {
const startBtn = document.getElementById("start");
const stopBtn = document.getElementById("stop");
const resetBtn = document.getElementById("reset");
// create a timer and assign it seconds as well as a callback function that is called every second
const timerDiv = document.getElementById("countdown");
const timer = new Timer(5, (seconds) => {
// called every seconds with seconds to go as an argument
timerDiv.textContent = `${seconds}s to go`
})
// add event listeners to buttons
startBtn.addEventListener("click", () => timer.start());
stopBtn.addEventListener("click", () => timer.stop());
resetBtn.addEventListener("click", () => timer.reset());
})
<div id="countdown"></div>
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="reset">Reset</button>
I'm trying to figure out how to set time out for function inside the loop iteration in Ionic TypeScript application.
setInterval makes equal time interval with calling the function in endless repetition:
setInterval(() => {
this.myFunc1(val);
}, 800);
setTimeout gives required result if listed sequentially:
setTimeout(() => {
this.myFunc1(val);
}, 800);
setTimeout(() => {
this.myFunc1(val);
}, 1200);
but how to loop with time interval trough the updated list and wait while pass second value val to the function, or call myFunc1 when it will be finished in previous iteration:
async myFunc2() {
for (let val of this.myValueList) {
/// wait for 5 sec or wait for finishing process, then pass value calling function:
this.myFunc1(val);
}
}
setInterval is the correct choice here. What's missing is that you need to clear the interval. setInterval returns an id that you can pass to clearInterval which stops the iteration.
Here I'm passing data to console.log, waiting a second, then repeating till done.
const myValueList = [5,6,7,8,9,10];
let i = 0;
const id = setInterval(() => {
console.log(myValueList[i++]);
if (i === myValueList.length) {
clearInterval(id);
console.log("done!");
}
}, 1000);
Simplest solution for waiting approximately 5 seconds:
const wait = t => new Promise(r => setTimeout(r, t));
and then in your code you can just do:
async myFunc2() {
for (let val of this.myValueList) {
await wait(5000);
this.myFunc1(val);
}
}
If myFunc1 is async, and you just want to wait for it to finish executing before continuing the loop, then you would just do:
async myFunc2() {
for (let val of this.myValueList) {
await this.myFunc1(val);
}
}
Hello I would like to put setInterval in my React project to add 1 for each second but I got an error like in title of this post.
js:
const [activeTab, setActiveTab] = useState(0)
useEffect(() => {
setInterval(setActiveTab(prevTab => {
if (prevTab === 3) return 0
console.log('hi')
return prevTab += 1
}), 1000)
})
There are a few issues:
You're not passing a function to setInterval, you're calling setActiveTab and passing its return value into setInterval.
If you were passing in a function, you'd be adding a new repeated timer every time your componennt ran. See the documentation — useEffect:
By default, effects run after every completed render...
And setInterval:
The setInterval() method... repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.
(my emphasis)
Starting a new repeating timer every time your component re-renders creates a lot of repeating timers.
Your component will leave the interval timer running if the component is unmounted. It should stop the interval timer.
To fix it, pass in a function, add a dependency array, and add a cleanup callback to stop the interval:
const [activeTab, setActiveTab] = useState(0);
useEffect(() => {
const handle = setInterval(() => { // *** A function
setActiveTab(prevTab => {
if (prevTab === 3) return 0;
console.log("?ghi");
return prevTab += 1;
});
}, 1000);
return () => { // *** Clear the interval on unmount
clearInterval(handle); // ***
}; // ***
}, []); // *** Empty dependency array = only run on mount
Side note: Assuming you don't need the console.log, that state setter callback function can be simpler by using the remainder operator:
setActiveTab(prevTab => (prevTab + 1) % 3);
useEffect(() => {
setInterval(() => {
setActiveTab((prevTab) => {
if (prevTab !== 3) {
return (prevTab += 1);
} else {
return 0;
} // console.log("hi");
});
}, 1000);
}, []);
If I want to execute the code on a given interval, I can use setInterval() function as below.
How to set a timeout to stop execution of setInterval method; not on counter but after given time period
let currentStatus = 'InProgress';
console.log(currentStatus);
if (currentStatus === 'InProgress') {
let timerId = setInterval(async () => {
console.log('tick')
}, 2000);
}
Just want to share a simple example for this, so posting this Q&A.
We can use setTimeout() function with clearInterval() to set the timeout, after which the execution of the code as specified by TimerHandler in setInterval will stop.
let currentStatus = 'InProgress';
console.log(currentStatus);
if (currentStatus === 'InProgress') {
let timerId = setInterval(async () => {
console.log('tick')
}, 2000);
// after 10 seconds stop
setTimeout(() => { clearInterval(timerId); console.log('stop'); }, 10000);
console.log('done');
}
See this link for details: https://javascript.info/settimeout-setinterval
I am trying to call the function test() as many times as possible in a given time interval.
Here the function should be running for 15 seconds.
function test(): void; // Only type def
function run() {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, 15000); // 15 seconds
while (true) {
test();
}
});
}
run()
.then(() => {
console.log('Ended');
});
However, the function doesn't stop running, and the Ended console.log does not appear. (Promise not resolved obviously). Is there a way to achieve this in Javascript ?
I was wondering, I could probably use console timers and put the condition in the while statement ? (But is that the best way ?)
The reason why your function does not stop executing is because resolving a promise does not stop script executing. What you want is to store a flag somewhere in your run() method, so that you can flip the flag once the promise is intended to be resolved.
See proof-of-concept below: I've shortened the period to 1.5s and added a dummy test() method just for illustration purpose:
let i = 0;
function test() {
console.log(`test: ${i++}`);
}
function run() {
return new Promise(resolve => {
let shouldInvoke = true;
setTimeout(() => {
shouldInvoke = false;
resolve();
}, 1500); // 15 seconds
const timer = setInterval(() => {
if (shouldInvoke)
test();
else
window.clearInterval(timer);
}, 0);
});
}
run()
.then(() => {
console.log('Ended');
});