Run code with a different outcome every 30 seconds - javascript

I have 2 variables called var1, and var2:
var var1 = 'foo';
var var2 = 'bar';
I'd like to be able to log one of these variables to the console every 30 seconds, with the variables alternating being logged (here's some pseudo-code):
Log var1 to console
Wait 30 seconds
Log var2 to console
Wait 30 seconds
Repeat
Any way to do this? I believe I should be doing something related with setInterval, but my solution:
setInterval(function() {
console.log(var1);
setTimeout(() => {
console.log(var2);
}, 30000);
}, 60000);
Doesn't seem to be the best solution. Is there a more efficient way to do this?

Just keep counter that enables you to alternate.
var counter = 0;
var var1 = "ONE!";
var var2 = "TWO!";
var frequency = 1000; //1000 is for illustration for the example
setInterval(function() {
if( counter++ % 2 == 0 ) {
console.log(var1);
} else {
console.log(var2);
}
}, frequency );

You want to use setInterval so that the interval is consistent and there is no execution time involved in establishing the time for the next async call.
You can pass in an object reference to control scope and also track the boolean and flip it:
setInterval(function(a){
a.bool = !a.bool
if(!a.bool){
console.log( a.var1)
return
}
console.log(a.var2)
}, 3000, {
bool : true,
var1 : 'value',
var2 : 'other value'
})

You could use setTimeout with two functions that call each other:
var var1 = 'foo';
var var2 = 'bar';
const log1 = () => {
console.log(var1);
setTimeout(log2, 30000)
}
const log2 = () => {
console.log(var2);
setTimeout(log1, 30000)
}
log1();

Here's a more generic approach: For a given list of values - it'll print the provided values in a cycle forever, and will wait for intervalMs between every print
/**
*
* #param {Array} values - collection of values to log
* #param {Number} intervalMs - the log interval
*/
function logValuesCyclicForever(values, intervalMs = 30000) {
let index = 0;
return setInterval(() => {
console.log(values[index]);
index = (index + 1) % values.length; // sets the location back to 0 when the last element is printed.
}, intervalMs);
}
var var1 = 'foo';
var var2 = 'bar';
logValuesCyclicForever([var1, var2]); // for your use case

Related

How do I setup a "rolling window"?

I'm trying to figure out the way I can set up a rolling window for a variable.
The variable will record a number increasing # amount of times from the minute before.
My basic interval timer
var kp123 = Number('1');
var myInt = setInterval(function () {
kp123 = 1;
}, 60000);
Whenever a specific command is sent, kp123 gets increased by 1:
kp123++;
This variable may increase 20 times every second, or only 2-3 times every second.
Right now how the system is set up, it records the variable # every minute, however, the data gets reset when the interval timer reaches one minute.
var kp123 = Number('1');
var kp123History = []; // The history of kp123 is stored in this variable each minute
var myInt = setInterval(function () {
kp123History.push(kp123);
kp123 = 1;
console.log(kp123History); // You can see the results in the console each minute like this
}, 60000);
or if you only want the previous value, and not the full history, try this
var kp123 = Number('1');
var prevKp123 = null; // The previous value of kp123 is stored in this variable each minute
var myInt = setInterval(function () {
prevKp123 = kp123;
kp123 = 1;
}, 60000);
It sounds like (per the comments) you want a rolling average (wiki). You don't really show enough of your code for me to give a specific answer to you, but in general, you can't deduce a rolling average from just averages, you'll need to know actual values and their timestamps. I.e. you can't summarize your data and throw away the timestmaps.
class RollingAverage {
constructor(windowMs = 1000) {
this.windowMs_ = windowMs;
this.values_ = [];
}
addValue(value = 1) {
let time = Date.now();
this.values_.push({value, time});
}
get average() {
let now = Date.now();
this.values_ = this.values_.filter(({time}) => now - time <= this.windowMs_ * 1000);
return this.values_
.map(({value}) => value)
.reduce((a, b) => a + b)
/ this.values_.length;
}
}
let test = async () => {
let sleep = ms => new Promise(r => setTimeout(r, ms));
let avg = new RollingAverage();
avg.addValue(1);
console.log(avg.average); // 1
await sleep(600);
console.log(avg.average); // 1
avg.addValue(3);
console.log(avg.average); // 2
await sleep(600);
console.log(avg.average); // 3
avg.addValue(5);
console.log(avg.average); // 4
}
test();

how to decrease number by using var

I have a variable equal to number, so I want decrease this variable value every second.
in this code it is print the same number over and over, although I have written
(n--)
var x = setInterval(function() {
var n = 50;
console.log(n--);
}, 1000);
my question how I can decrease it?
You could use a IIFE with a closure about the value. Tha advantage is to use a local variable without polluting the global space.
var x = setInterval(function(n) {
return function() {
console.log(n--);
};
}(100), 1000);
And here is one without the need of a global variable but using IIFE:
var x = setInterval(
(startValue => () => {
console.log(startValue--);
})(100),
1000
);
Checkout this: it will stop when x will equals to zero
var x = 100;
var handler = setInterval(function(){
x--;
console.log(x);
if(x === 0)
clearInterval(handler)
} , 1000)
Your code issue is that you put the -- sign after and It should be before(--n) and It also you have declared var n = 50 inside to loop of setInterval, at this way each time that It's executed n variable always is 50, you should to put this varible at the start of yout code.
var n = 50;
var x = setInterval(function() {
console.log(--n);
}, 1000);

How to use this keyword?

Hi I'm making a pomodoro clock. I want to allow the timer to increase or decrease every 100 milliseconds when the user holds down the button. The running conditions for mousedown and clickUpdate are very similar.
The entire code of clickUpdate relies on using this keyword to achieve that goal. But how can I let setInterval inherit or have access to this keyword? This referring to the button object that mousedown is a method of.
https://codepen.io/jenlky/pen/ypQjPa?editors=0010
var timer;
const session = document.getElementById("session");
const breaktime = document.getElementById("break");
const mins = document.getElementById("mins");
const secs = document.getElementById("secs");
function clickUpdate () {
// if data-action = increase and its under session-input, increase session.value else increase breaktime.value
if (this.dataset.action === "increase") {
if (this.parentElement.className === "session-input") {
// if session.value is 60 mins, this increase click changes it to 1 min
if (session.value === "60") {
session.value = 1;
} else {
session.value = Number(session.value) + 1;
}
mins.innerText = session.value;
// if breaktime.value is 60 mins, this increase click changes it to 1 min
} else {
if (breaktime.value === "60") {
breaktime.value = 1;
} else {
breaktime.value = Number(breaktime.value) + 1;
}
}
}
// if data-action = decrease and its under session-input, decrease session.value else decrease breaktime.value
if (this.dataset.action === "decrease") {
if (this.parentElement.className === "session-input") {
// if session.value is 1 min, this decrease click changes it to 60 mins
if (session.value === "1") {
session.value = 60;
} else {
session.value = Number(session.value) - 1;
}
mins.innerText = session.value;
// if breaktime.value is 1 min, this decrease click changes it to 60 mins
} else {
if (breaktime.value === "1") {
breaktime.value = 60;
} else {
breaktime.value = Number(breaktime.value) - 1;
}
}
}
console.log(this);
}
// Problem is how can I let clickUpdate or setInterval(function(){},100) inherit this
// setInterval's function doesn't seem to inherit or have any parameters
// I'm not sure how forEach thisArg parameter works, or how to use bind, or how to use addEventListener last parameter
function mousedown() {
var obj = this;
timer = setInterval(clickUpdate, 100);
}
function mouseup() {
if (timer) {
clearInterval(timer);
}
}
const buttons = Array.from(document.getElementsByClassName("symbol"));
mins.innerText = session.value;
//buttons.forEach(button => button.addEventListener("click", clickUpdate));
buttons.forEach(button => button.addEventListener("mousedown", mousedown));
buttons.forEach(button => button.addEventListener("mouseup", mouseup));
console.log(session);
The this value within functions defined using function () ... is usually dependent on how the function is called. If you call a.myFunction() then this within the function will be a reference to a. If you call myFunction(), then this will either be undefined or the global object depending on whether you are using strict or sloppy mode.
Usually the most straightforward way to get a callback function to use a particular this value is to use .bind(n). This basically creates a wrapped version of the original function, with the this value locked in as n
setInterval(clickUpdate.bind(this), 100);
Then again, my preference would be to not use this at all. It's confusing and has wacky behavior that often requires all sorts of contrived workarounds (as you have experienced). You could just as easily pass in the value as a parameter here:
function mousedown(e) {
timer = setInterval(clickUpdate, 100, e.target);
}
One trick is to create a separate reference (either global or at least on a common ancestor scope) holding the reference to the "this" reference from the level you want.
Once you do that, you can refer to it within the setInterval function.
Example:
var scope = this;
this.name = 'test';
setInterval(function() {
console.log(scope.name); // should print 'test' every 1 second
},1000);

Javascript error with returns and multiple the return

And I am sorry to bother with this noob-stuff, but currently new to all this. But learning slowly.
In the first lines of code im getting a return (in this code i get 20*2=40. in the next phase I want to multiplie the return (40) with 20. = 800. so in the outcome it will show 40 And 800. But i only get it to be in the outbox [function], it says. and a msg; "it looks like you didnt print out a value for newNumber".
What do I do wrong? Thanks for all help!
var timesTwo = function (number) {
return number * 2;
};
timesTwo(20);
var newNumber = function (tal) {
(timesTwo * tal);
console.log(newNumber);
};
newNumber(20);
What you need to do is assign the result to a variable, and in the second function return the result:
var timesTwo = function(number) {
return number * 2;
};
var twoTimesResult = timesTwo(20);
var newNumber = function (tal) {
return twoTimesResult * tal;
};
var result2 = newNumber(20);
console.log(result2);
If you wanted to be fancy you could also do the following:
function multiplier(num, multiplier) {
var by = num * multiplier;
return function (number) {
return number * by;
};
}
var multiplyResult = multiplier(20, 2);
console.log(multiplyResult(20));
I'm answering this question too because I think these types of things are fun.
Another approach you could take is the OOP approach.
From your example you have a common multiplier of 20 and a beginning constant of 2.
I would personally attack this problem like so to avoid multiple variables:
// Create a calc object
var Calc = (function () {
// Constructor
Calc = function () {
// Initial constant
this.current_val = 2;
}
// Prototype methods
Calc.prototype = {
// inc() method
inc: function () {
return this.current_val * 20;
}
}
// Return object
return Calc;
})();
// Object Instance
var obj = new Calc();
// Initial call to inc() -> 40
obj.current_val = obj.inc();
// Log
console.log(obj.current_val);
// Second call to inc() -> 800
obj.current_val = obj.inc();
// Log
console.log(obj.current_val);
// Third call to inc() -> 16000
obj.current_val = obj.inc();
// Log
console.log(obj.current_val);
I made a jsfiddle so you can see the output.

Looping over contents of a JSON without reloading the page

I have a JSON array(?) of pairs of every state and a value associated with that state, it looks like the following below:
var states = [{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}]
I need the page to shuffle through them without reloading the page
"AL 6" [wait x seconds] then "AK 3" [wait x seconds] then etc...
I need this to run continuously.
I never use any of these languages but was told that they were my best bet.
Could someone give me some guidance on this please.
Thank you in advance.
Here's a jsfiddle with setInterval execting a function that alternates between each state and displays it in a div:
http://jsfiddle.net/WD5Qj/1/
var states = '[{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}]';
json = jQuery.parseJSON(states);
var i = 0;
var cycle = function(){
$("#state").html(json[i].STATE + json[i].AMOUNT);
i = (i+1)%json.length;
}
var loop = setInterval(cycle, 500);
Alright, you'd need a function that does the rotation through the array, and a variable for keeping the current state (in both meanings of the word):
var stateIndex = 0;
function rotate() {
stateIndex++;
if(stateIndex >= states.length)
stateIndex = 0;
displayState(states[stateIndex]);
}
And you'd need an interval to perform the rotation:
var stateRotation = window.setInterval(rotate, 3000); // 3000ms = 3 sec
The stateRotation variable is an identifier of your interval. You may use that if you ever want to stop: window.clearInterval(stateRotation);
Now, the above code anticipates a function displayState which takes a state object and displays it. How that would look depends entirely on how you want your state to displayed. In its simplest form, something like this:
function displayState(state) {
$('#state-name').html(state.STATE);
$('#state-amount').html(state.AMOUNT);
}
As per your description, it might perhaps be something more like
$('#state-text').html(state.STATE + ' ' + state.AMOUNT);
var states = [{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}];
var i = 0;
setInterval(function(){
var array_index = i % states.length;
$('#state').html( states[ array_index ]['STATE'] );
$('#state').html( states[ array_index ]['AMOUNT'] );
i++;
}, 2000);
Here's a fiddle.
function displayNextItem(index){
if (index === states.length)
displayNextItem(0);
$("#someDiv").text(states[index]["STATE"] + " " + states[index]["AMOUNT"]);
setTimeout(function() { displayNextItem(index + 1); }, 1000);
}
And then
displayNextItem(0);
var i = 0, l = states.length, timer, intervalLength = 5000;
timer = setInterval(function(){
if(i >= l){
clearInterval(timer);
}else{
alert(states[i++].STATE);
}
},intervalLength);
This implementation is waiting the AMOUNT number of seconds. If you want constant number of seconds then other answers are better :).
JavaScript:
var states = [{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}];
function iterate(index) {
var time = states[index].AMOUNT;
// replace the text with new one
$("#output").text(states[index].STATE + " " + time);
setTimeout(function() {
var next = (index + 1) % states.length;
iterate(next);
}, time * 1000);
}
iterate(0);
HERE is the code.

Categories