I would like to periodically call a function (assume it's name is "alter(id)") with the parameter changing every call. The parameter should increment with every call and return to 0 at some point. On a timeline it would look like this:
Time: function to call
0ms: alter(0)
300ms: alter(1)
600ms: alter(2)
900ms: alter(3)
1200ms: alter(0)
1500ms: alter(1)
and so on ad infinitum.
let counter = 0; // closure
const INTERVAL = 300;// 300ms
const alter = (arg) => { /* alter function body */ }
const tick = () => {
counter = alter(counter);
counter = a < 3 ? a + 1: 0;
}
tick(); // 0ms
setInterval(tick, INTERVAL); // call each 300 ms
setInterval documentation
closure
Related
I have a simple game loop that goes like this:
function update(progress){
//do something each second
//do something else twice per second
//do something else each two seconds
}
function draw() {
//code here...
}
function gameLoop(timestamp) {
update(progress)
draw()
var progress = (timestamp - lastRender)
lastRender = timestamp
window.requestAnimationFrame(gameLoop)
}
var lastRender = 0
window.requestAnimationFrame(gameLoop)
How can I make sure to execute some actions into the update function each helf second, second, or two seconds?
Thank you
If you want to define the interval, you'll need to use setInterval. requestAnimationFrame will only update based on the refresh rate of the screen so you cannot define your own interval with this. setInterval has lots of downsides though, so it is recommended to sync up the interval with the refresh rate using something like this:
let doUpdate = false
setInterval(() => doUpdate = true), 1000)
const render = () => {
if (doUpdate) {
// your code
doUpdate = false
}
}
window.requestAnimationFrame(render)
If you want to perform an action periodically when using game loop based on delta time, the basic idea is for you to keep a counter of the elapsed time. For each iteration, you then add the time difference until it reaches the intended period.
Applied to your code, it would look something like this:
let oneSecondCounter = 0
let twoSecondCounter = 0
function update(progress){
oneSecondCounter += progress
if (oneSecondCounter >= 1000) {
// Code here will be executed every 1000ms
oneSecondCounter = 0
}
twoSecondCounter += progress
if (twoSecondCounter >= 2000) {
// Code here will be executed every 2000ms
twoSecondCounter = 0
}
}
function draw() {}
function gameLoop(timestamp) {
var progress = (timestamp - lastRender)
update(progress)
draw()
lastRender = timestamp
window.requestAnimationFrame(gameLoop)
}
var lastRender = performance.now()
window.requestAnimationFrame(gameLoop)
However, this means you have to make a counter variable for every periodic action you want to perform. Instead of creating a separate variable, we can bundle the counter together with the function using a closure. The closure lets each function to have their own independent counter.
The closure that we are going to use looks like this:
function initPeriodicFunction(fn, runEvery) {
let counter = 0
return function (deltaTime) {
counter += deltaTime
if (counter >= runEvery) {
fn()
counter = 0
}
}
}
Now, instead of having to create a counter variable for each action, we can just pass a function to the initPeriodicFunction and get a new function which will run only periodically.
// You can use an arrow function
const runEverySecond = initPeriodicFunction(() => console.log('One second'), 1000)
// Or you can pass a function
function runThis() {
console.log('Two seconds')
}
const runEveryTwoSeconds = initPeriodicFunction(runThis, 2000)
function update(progress){
runEverySecond(progress)
runEveryTwoSeconds(progress)
}
Depending on your use case, the method above might be enough. If you're going to perform a more accurate tasks (e.g. physics engine), it would be better to separate the frame rate from the update rate. This is similar to how Unity's FixedUpdate works.
Imagine you want to perform a physics update every 100ms. If somehow the update call was delayed, for example 600ms after the last update, instead of performing a single update, we perform 6 updates, each with 100ms chunk. This results in more precise step-by-step calculation.
To perform this kind of fixed update, the initialization function need to be modified as follows:
function initPeriodicFunction(fn, runEvery) {
let counter = 0
return function (deltaTime) {
counter += deltaTime
while (counter >= runEvery) {
fn()
counter -= runEvery
}
}
}
Now, the function will be run either once or multiple times depending on how long has elapsed since the last update call.
setInterval(function {
//code that happends every second goes here
}, 1000);
use setInterval().
This creates a timer and will call the function every x seconds.
I want to call a method 5 times in every one second. for example I have a methodA which i want to execute this method in 5 times in every 1 second. so how can i do it.
methodA(){
console.log("called")
}
timePeriod(){
setimeout....
}
You can do it with setInterval()
const test = setInterval(() => console.log("Hello method"),1000);
setTimeout( () => clearInterval(test), 5000);
Hope it is what you need!
let timePeriod = 1000 // 1000 ms
function methodA(){
console.log("called")
}
setInterval(methodA, timePeriod)
notice here that we pass the function as an argument without () which in other words we're referencing the function. Note that if you pass the function name along with () it means you're calling it independently
Also, keep in mind that setInterval works a little bit different than you might think as it's a macro task asynchronous function in the event loop. if you don't know about the event loop simply all you need to know that setInterval doesn't actually call the function unless the rest of you script gets fired + the time period you specify
setInterval = the time needed to fire the rest of the script + the time period you specify
and what you can do to test this is:
const tick = Date.now(), timeLog = (val='---') => console.log(`${val} \n Elapsed: ${Date.now() - tick} ms`)
setInterval(_ => timeLog('smth from setInterval'), 1000)
for(let i=1;i<1000000000;i++){
// this loop will run for 1B times so that we get a clear time delay
}
timeLog('smth from normal console.log')
const Comp= () => {
const methodA=()=>{
// statement here
}
useEffect(()=>{
let a = setInterval(methodA,1000/5)
return(()=>{
clearInterval(a)
},[])
})
return(<></>)
}
Try to use interval inside useEffect hook.
One could control both, the interval itself and also the condition for terminating the running interval, by writing a utility/helper function which enables not only clocked functions but also clocked methods.
function clocked(interval, isTerminate, proceed, target) {
let count = 0;
let intervalId = setInterval(() => {
proceed.call(target ?? null);
if (isTerminate(++count)) {
clearInterval(intervalId);
}
}, interval);
}
const obj = {
text: "The quick brown fox jumps over the lazy dog.",
log() {
console.log(this.text);
},
};
function doTerminateWhen(counter) {
return counter >= 5;
}
setTimeout(() => { console.log('1.001 seconds passed'); }, 1001);
clocked(200, doTerminateWhen, obj.log, obj);
setTimeout(() => { console.log('1 second passed'); }, 1000);
.as-console-wrapper { min-height: 100%!important; top: 0; }
setInterval is being used her to call the methodA function at each once second and modCall function has a for loop to iterate and call the setInterval the number of times specified in its paramter
function methodA(i){
console.log('call '+i)
}
function modCall(len){
for(let i=0;i<len;i++){
setInterval(()=>methodA(i),1000)
}
}
modCall(5) //5 is number of time you want to call the methodA
var time = 1000;
var point = 0;
function interval() { timeout = setTimeout(increment, time);}
function increment(){point += 1;document.getElementById("pul").value = point;interval();}
time2 = 3000;
function fermafatica() {setInterval(ferma, time2);}
function ferma(){clearTimeout(timeout)}
i need to stop the interval() function or the setTimeout in interval() for only 1000ms and then to keep it working
Are you asking about how to clear a timeout after X seconds? I would consider just having a static variable (lets just call it X) count up within the repeating function, and if the function repeats every 10ms, and you want it to run for 1000ms, then when x==100, clear the timeout.
You could try:
setTimeout(function() {
z();
// Do anything else here
}, 1000);
The setTimeout function, runs the given function after a set amount of time. This will call the z() function, which clears your timeout, after the supplied time of 1000ms.
EDIT: Everything: See below
var time = 1000;
var point = 0;
function interval() { timeout = setTimeout(increment, time);}
function increment(){point += 1;document.getElementById("pul").value = point;interval();}
time2 = 3000;
function fermafatica() {setInterval(ferma, time2);}
function ferma(){clearTimeout(timeout)}
Change function fermafatica() {setInterval(ferma, time);}
to function fermafatica() {setTimeout(ferma, time);}
ok.... i "avoid" the problem.... i need to stop the setTimeout for 1000ms and then let it works normally... i tried so... instead of pausing the setTimeout I put another time var.
var time = 1000;
var timecache = 1000;
fatica = 3000;
sudore = 3000;
function interval() { timeout = setTimeout(increment, time);} //here setTimeout uses var time//
function increment(){console.log(time);point += 1;document.getElementById("pul").value = point;interval();}
function fermafatica() {time = timecache;setInterval(ferma, fatica);} //here the function equals time to timecache so vas time is always 1000ms//
function ferma(){time = 10000; setTimeout(fermafatica, sudore);} // then here I transformed the time in 10000 so the first function will take 10000 instead of 1000 in setTimeout//
//plus i put a setTimeout to recall function fermafatica() that reset the time to 1000//
this i what i want... I avoid the problem and found another way to do that... but it works...
Right now i have this 1 minute timer in my background page that runs forever i would like to be able to start and stop it from an options page.
chrome.browserAction.setBadgeBackgroundColor({color:[0, 0, 0, 255]});
var i = 1;
window.setInterval(function(timer) {
chrome.browserAction.setBadgeText({text:String(i)});
i++;
}, 60000);
setInterval() method of the Window object schedules a function to be invoked repeatedly at intervals of the specified number of milliseconds. setInterval() returns an opaque value that can be passed to clearInterval() to cancel any future invocations of the scheduled function. Read more about How Javascript Timers work. With that you can write something like this:
My.Controller = {};
(function() {
var interval = 10;
var timer = null;
function init (param) {
// initialisations if any
}
// Override the default interval of 10 seconds by passing new interval
function startAction (param, tInterval) {
// Set a timer
var ti = (!tInterval) ? interval : tInterval;
timer = setInterval(My.Controller.action, ti * 2000);
}
function action () {
// Logic here
}
function stopAction () { clearInterval(timer); }
var c = My.Controller;
c.init = init;
c.startAction = startAction;
c.stopAction = stopAction;
})(); // end Controller
Now you can say My.Controller.startAction() to start the timer and and My.Controller.stopAction() to stop.
Read and explore about namespaces in JavaScript.
Hope this helps.
I used window.setInterval function. this function includes 3 arguments :
setInterval(code,millisec,lang)
I used that like this:
var counter = 1;
window.setInterval(function() {}, 1000 * ++counter);
but when first time set timer (second argument), is not changed and that act Like below code:
window.setInterval(function() {}, 1000);
please write correct code for change timer
Use window.setTimeout instead.
var delay = 1000;
function myTimer() {
// do whatever
window.setTimeout(myTimer, delay);
}
window.setTimeout(myTimer, delay);
You can manipulate delay in the body of your function.
Your problem is that javascript first execute '1000 * ++counter' once and then do not update the time interval.
You should try to use a timeout instead: https://developer.mozilla.org/en/DOM/window.setTimeout
And create a new time out with the new value every time your time out function is called.
Sounds like what you're after is not setInterval but rather setTimeout in a loop:
var counter = 1;
for (var i = 1; i <= 3; i++) {
window.setTimeout(function() {
alert("#" + counter);
counter++;
}, i * 1000);
}
This will execute three different "timers" one after the other.
Live test case: http://jsfiddle.net/86DRd/