Is it possible to have a variable interval within a javascript function? - javascript

I've been trying without success to set up a way of varying the interval used when incrementing a value by one. It's set to increment every 9 seconds but I'd like the counter to look a little less robotic and instead increment by a repeated variation of numbers, for example, 3 seconds, 7 seconds, 12 seconds, 10 seconds and 13 seconds (the five numbers add up to 45 to ensure an average of 9 seconds is maintained).
I've tried to put these numbers into an array and loop the value of 'interval' through them but I've now realised that value can't be changed within the context of the function once it's started.
Would be super grateful for any advice here. Thanks!
Current code for more 'robotic' count:
let interval = 9000;
let shiftCounter = {{ row.total }};
window.setInterval(function () {
document.getElementById("shiftsCreated").innerHTML = shiftCounter.toLocaleString('en');
shiftCounter = shiftCounter + 1;
}, interval);

You can use setTimeout instead, and every time it completes, call new timeout by choosing random delay or whatever order you want.
let counter = 0;
const intervals = [3, 7, 10, 12]
increment(0);
function increment(timeout) {
setTimeout(() => {
console.log(`Counter: ${counter}.`)
counter++;
increment(intervals[Math.floor(Math.random() * intervals.length)] * 1000)
}, timeout);
}

Related

How to smoothly increase a number to Y in X milliseconds exponentially

I'm making a semi-realistic 'physics' engine in node.js, if you can even call it that and I want to accelerate exponentially. E.g. from 0m/s to 4.5m/s in 2 seconds, then maybe decelerate to 0m/s in 3 seconds. Obviously for the deceleration part I can probably get away with inputting a negative number.
Here's a picture of what I'm thinking of, not sure if what I expect in the graph is the same thing as exponents.
I don't have any code, I thought I could base it off something like setInterval, but that would be linear.
You're right SetInterval can only provide with a fixed speed whereas what you need is dynamic speed.
One way is to make two arrays with an equal number of items. With first array named duration and second name speed. The variable Y will be changed by the speed for the duration corresponding to the # of the speed. See here :
var Y = 0; // The variable that is to be changed
var speed = [4.5, 0, -4.5]; // The acceleration in m/s
var time = [2, 4, 2]; // Duration corresponding to each acceleration in s
var sec = 1000; // 1 second = 1000 milliseconds
var i = 0; // A counter to remember the item number in the arrays
var dur = 0; // A variable to hold the duration for which a particular speed has currently lasted. This variable helps to validate the duration for which the Y is changed.
// The function that holds the logic
function tick() {
// Checking if duration is equal to or has crossed the user specified duration for the speed
if(dur >= time[i]*1000){
// If yes, move on to the next speed and duration
i++;
dur = 0;
if(i > speed.length-1){clearInterval(loop);} // If there are no more items in the array stop the interval
}
else {
// If not, continue increasing Y and dur
Y = Math.round(Y*1000 + (speed[i]/50)*1000)/1000 // A simple workaround to avoid the error in arthimetic calculation that occurs while using floats (decimal numbers) in JS.
console.log(Y); // This line is only for debugging purposes. IT CAN BE REMOVED
dur += sec/50;
}
}
var loop = setInterval(tick, sec/50);

Count how many times document.hasFocus returns "true", if it's equal or greater than 15 do something

I'm using setInterval to check every second for document.hasFocus(), so every second it returns true or false.
setInterval(function() {
console.log(document.hasFocus());
}, 1000);
When the return of true is equal to or greater than 15, I would like to do something. I wrote the code below (which obviously doesn't work) to make it easier to understand what I want to achieve.
if (document.hasFocus()) ≥ 15 {
do something
}
Could anyone help me with this?
document.hasFocus() returns a boolean not a number.
So you can use a counter and increment it each time document.hasFocus() returns true.
Then you can test the counter.
As far as I can see, you just want to count for 15 times before calling some function or executing some logic, the variable that is responsible for counting represents your application state. So we will call it count
let count = 0;
then we just increment count while the condition is met every second, until finally we stop the interval when the condition is met
let intervalToken = setInterval(function checkDocument(){
if(document.hasFocus()){
count = count + 1;
if(count > 15){
clearInterval(intervalToken); // stop intervale here
callMyFunction(); // call your function here
}
}
}, 1000)
Simply add a counter like this:
let counter = 0;
if (document.hasFocus() && ++counter >= 15) {
alert('you did it!');
}
You just need a variable to count the number of times document.hasFocus().
let focusCount = 0;
setInterval(() => {
focusCount = document.hasFocus() ? focusCount + 1 : focusCount;
if (focusCount >= 15) {
console.log(focusCount);
}
}, 1000);

Creating a Countdown with JavaScript

I am trying to make a Countdown that just log in the terminal the seconds remaining. It should be an interval of 1 second between every log. It has to be as a method of an object. I don´t know if it's because of the scope but somehow it's not working after many trials and code-rewriting.
Anybody can help me with this?
var Countdown = function(seconds) {
this.counter = seconds;
this.start = function() {
setTimeout(
function() {
while (this.counter >= 0) {
console.log(this.counter);
this.counter -= 1;
}
},1000)
}
}
I would use a setInterval() for a simple countdown timer. I would also write my function for the math loop outside of the setInterval and then call on the function within the interval, like the following => setInterval(timerFunction(), 1000). There is no need for a loop when you use the interval, it does the looping each defined time increment as set in your setInterval(). Each time the interval fires, the function will do its thing.
EDIT: added a conditional to see if the interval time has run out.
I have included an example of a simple count down timer in my answer below along with notation inside the code that helps to explain further. Hope this helps.
Also, by terminal, I assume you mean the console? My example displays the setInterval in the console...
let sMin = 2; // amount of minutes you wish to start with
let time = sMin * 60; // format for minutes by multiplying by 60 as we have 60 seconds in each minute
let countdown = setInterval(update, 1000) // set up a setInterval for the countdown function
// create a function that will countdown the seconds
function update() {
// define our minutes using Math.floor(time / 60)
let min = Math.floor(time / 60);
// define our seconds by modulating time with 60, our seconds units
let sec = time % 60;
// tenerary conditional to see if seconds is set to 0 for proper display of formatting as seconds
sec = sec < 10 ? '0' + sec : sec;
// display the countdown timer in time format using the minutes and seconds variables
console.log(`${min}:${sec}`);
// decrement time by one second with each interval as set in the setInterval call `1000`
time--;
// clear the interval if the minutes and seconds are both set to 0
min == 0 && sec == 0 ? clearInterval(countdown) : countdown;
}
Yes it was because of the scope. As you are using this inside setTimeout() it uses the global scope.
var Countdown = function(seconds) {
this.counter = seconds;
this.start = function() {
setTimeout(
function() {
while (this.counter >= 0) {
console.log(this.counter);
this.counter -= 1;
}
}.bind(this),1000)
}
}
I'm using bind to set "this" to current context.
And with reference to your question about timeout, instead of using setTimeout() use setInterval() to achieve your need about log with respect to seconds
function countDown(whileCountingDown, forHowLong, whenFinishedThen){
//error handling begin(for user's understanding)
if(arguments.length<3){return RangeError("ALL three arguments must be used")}
var typeErrors=[]
if(typeof whileCountingDown!="function"){typeErrors.push("whileCountingDown MUST be a function")}
if(typeof forHowLong!="number"){typeErrors.push("forHowLong MUST be a number(and it represents seconds)")}
if(typeof whenFinishedThen!="function"){typeErrors.push("whenFinishedThen MUST be a function")}
if(typeErrors.length>0){return TypeError(`There are ${typeErrors.length} parameters that are incorrect data types\n\n${typeErrors.join('\n')}`)}
//error handling begin(for user's understanding)
//........................................................................................................................
//the part that matters to you once you enter correct stuff
var i=setInterval(()=>{forHowLong--
if(forHowLong<=0){//count finished, determine what happens next
clearInterval(i); whenFinishedThen()
}
else{whileCountingDown(forHowLong)}//do this for each second of countdown
},1000)
}
console.log("The timers in the console and on the html element are 2 DIFFERENT countdowns")
//example use
countDown((m)=>{console.log(`${m} seconds left`)}, 30, ()=>{console.log('Cheers, the countdown is OVER')})
//obviously you can do stuff like edit randomHTML-Element.innerText for each second of the countdown or anything as you so desire since what i made is kindof flexible
//..........................................................................................................................
//more examples
//now for some fun stuff, we're gonna be editing an html structure, but first, we're going to make a 'timeParse' function to make it look kind of elegant
function timeParse(seconds){
//yup, error handling begin
if(typeof seconds!="number"){return TypeError("The parameter 'seconds' MUST be a number")}
//yup, error handling end
//below is the stuff to look at
var timeArr=[seconds]
if(timeArr[0]>=60){//if seconds >= 1 minute
timeArr.unshift(Math.floor(timeArr[0]/60))
timeArr[1]=timeArr[1]%60
if(timeArr[0]>=60){//if minutes >= 1 hour
timeArr.unshift(Math.floor(timeArr[0]/60))
timeArr[1]=timeArr[1]%60
if(timeArr[0]>=24){//if hours >= 1 day
timeArr.unshift(`${Math.floor(timeArr[0]/24)}d`)
timeArr[1]=timeArr[1]%24
}
}
}
return(timeArr.join`:`)
}
//now for applying countDown to things other than the console
function countDownAgain(){//just something that will show the flexibility of what i made.. im going above and beyond because i wanna look back on my answers as notes on how to do things(also ez copy pasting for future me xD)
countDown(
(s)=>{document.getElementById('toTime').innerText="Second Count "+timeParse(s)},
86401,
()=>{document.getElementById('toTime').innerText="No way you waited that long LOL"}
)
}
countDown(
(s)=>{document.getElementById('toTime').innerText="First Count "+timeParse(s)},
100,
countDownAgain
)
<div style="background-color:red;height:100px;text-align:center;line-height:50px"><h1 id="toTime">Count Down Time :}</h1></div>

Interval is too slow

Interval isn't running once per millisecond. The final number only gets to 459 before stopping. Less if there is more than just a line on the interval. On here it doesn't even move through the first thousand. What I want is for it to run once per second to let me know how far an interval is done. So if testNum is at 30, then I know that it's 97% of the way done (2970/3000).
let testNum = 3000
let testInt = setInterval(() => {
testNum--
}, 1)
let testTimeout = setTimeout(() => {
clearInterval(testInt)
console.log('Final Number: ' + testNum)
}, 3000)
From https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval#Parameters:
delay
The time, in milliseconds (thousandths of a second), the timer should delay in between executions of the specified function or code. If this parameter is less than 10, a value of 10 is used.
Have a look at Reasons for delays longer than specified as well.

Skip a setInterval every X loop?

I have a function that gets triggered every 10 seconds with a setInterval(); loop, and I'd like it to skip a call every 60 seconds. So the function would be executed at 10s, 20s, 30s, 40s and 50s but wouldn't be called at 60s, then gets called at 70s and so on.
Is there any straightforward way to do this, or do I have to tinker with incrementing a variable?
Thanks!
Do like this, use the simple modulo math and a counter.
var count = 0;
var interval = setInterval(function(){
count += 1;
if(count % 6 !== 0) {
// your code
}
}, 10000);

Categories