Moment JS subtract problems - javascript

I'm setting up a timer with moment, is not the only one I have in this screen but this doesn't work:
const halfBellTimer = () => {
const x = setInterval(() => {
let countTime = moment.duration().add({seconds: meditationTime / 2});
if (countTime <= 0) {
console.log('STOP');
} else {
countTime = countTime.subtract(1, 's');
console.log(countTime.seconds());
}
}, 1000);
};
It sets the time correctly but I get a log of the same value, so it doesn't subtract it.
Any idea?
Thanks!

If you move let countTime = moment.duration().add({seconds: meditationTime / 2});
outside of setInterval function it works fine.
Don't forget to clean up with clearInterval.
Take a look at the example.
const halfBellTimer = () => {
const meditationTime = 10;
let countTime = moment.duration().add({
seconds: meditationTime / 2
});
const x = setInterval(() => {
if (countTime <= 0) {
console.log('STOP');
clearInterval(x);
} else {
countTime = countTime.subtract(1, 's');
console.log(countTime.seconds());
}
}, 1000);
};
halfBellTimer();
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.1/moment.min.js"></script>

Related

Rolling numbers in js

I created rolling numbers
On the site I'm building in React.
How do I make it start working that it gets to the working place that it is?
It's starting to work for me that the page comes up
const RollingNumbers = () => {
useEffect(() => {
let valueDisplays = document.querySelectorAll(".amount");
let interval = 4000;
valueDisplays.forEach((valueDisplay) => {
let startValue = 0;
let endValue = parseInt(valueDisplay.getAttribute("data-val"));
let duration = Math.floor(interval / endValue);
let counter = setInterval(function () {
startValue += 1;
valueDisplay.textContent = startValue;
if (startValue === endValue) {
clearInterval(counter);
}
}, duration);
});
enter image description here
Thank you

How to update setInterval data every x seconds without affecting inside setInterval?

How can i update ranType every 30 seconds.
since ranType is random if ranType === 'works' how to add interval to update inside data every 10 seconds.
This is what i tried:
setInterval(() => {
let type = ['works', 'testing'];
let ranType = type[Math.floor(Math.random() * type.length)];
if (ranType === 'works') {
setInterval(async () => {
console.log(`Okay Working ${RANDOM DATA}`);
}, 10000);
} else {
setInterval(async () => {
console.log(`Testing also working ${RANDOM DATA}`);
}, 10000); // But RANDOM DATA should update every 10 seconds - I have RANDON data
}
}, 30000); // ranType should update every 30 seconds
expected output:
After 30 seconds
if ranType is 'works'
it should repeat console with random data every 10 seconds
Again after 30 seconds it (ranType) should change to testing
if ranType is 'testing'
it should repeat console with other random data every 10 seconds
Other issues is its keep repeting 3-4 times every 10 seconds.
Ok, I think this is what you want, please let me know if is not the expected result. Every 30 seconds the outer setInterval clears the last intervalId and creates a new one.
let intervalId;
setInterval(() => {
let type = ["works", "testing"];
let ranType = type[Math.floor(Math.random() * type.length)];
console.log("new cycle of interval of 30 seconds");
clearInterval(intervalId);
setTimeout(() => {
if (ranType === "works") {
intervalId = setInterval(async () => {
console.log(`Okay Working`);
}, 10000);
} else {
intervalId = setInterval(async () => {
console.log(`Testing also working`);
}, 10000);
}
});
}, 30000);
EDIT
created a new version which might be clearer
const setIntervalXTimes = (callback, delay, repetitions) => {
let count = 0;
let intervalID = setInterval(() => {
if (count === repetitions) {
clearInterval(intervalID);
} else {
callback();
}
count++;
}, delay);
};
setInterval(() => {
let type = ["works", "testing"];
let ranType = type[Math.floor(Math.random() * type.length)];
if (ranType === "works") {
setIntervalXTimes(() => console.log(`Okay Working`), 1000, 3);
} else {
setIntervalXTimes(() => console.log(`Testing also working`), 1000, 3);
}
}, 3000);
const ranType_reset_period = 30000;
const works_reset_period = 10000;
const testing_reset_period = 10000;
const random_data_reset_period = 10000;
let works_interval = -1;
let testing_interval = -1;
let RANDOM_DATA = "RANDOM_DATA_DEFAULT";
function reset_random_data() {
let sample_random_data = ['RANDOM_DATA_1', 'RANDOM_DATA_2', 'RANDOM_DATA_3', 'RANDOM_DATA_4'];
RANDOM_DATA = sample_random_data[Math.floor(Math.random() * sample_random_data.length)];
console.log('RANDOM_DATA', 'RESET', RANDOM_DATA);
}
function get_random_ranType() {
let type = ['works', 'testing'];
return type[Math.floor(Math.random() * type.length)];
}
function reset_works_interval() {
console.log(`Okay Working ${RANDOM_DATA}`);
}
function reset_testing_interval() {
console.log(`Testing also working ${RANDOM_DATA}`);
}
function reset_rantype() {
clearInterval(works_interval);
clearInterval(testing_interval);
if (get_random_ranType() === 'works') {
works_interval = setInterval(reset_works_interval, works_reset_period);
} else {
testing_interval = setInterval(reset_testing_interval, testing_reset_period); // But RANDOM DATA should update every 10 seconds - I have RANDON data
}
}
setInterval(reset_random_data, random_data_reset_period);
setInterval(reset_rantype, ranType_reset_period);
Illustration
const ranType_reset_period = 30000;
const works_reset_period = 10000;
const testing_reset_period = 10000;
const random_data_reset_period = 10000;
let works_interval = -1;
let testing_interval = -1;
let RANDOM_DATA = "RANDOM_DATA_DEFAULT";
function reset_random_data() {
let sample_random_data = ['RANDOM_DATA_1', 'RANDOM_DATA_2', 'RANDOM_DATA_3', 'RANDOM_DATA_4'];
RANDOM_DATA = sample_random_data[Math.floor(Math.random() * sample_random_data.length)];
console.log('RANDOM_DATA', 'RESET', RANDOM_DATA);
}
function get_random_ranType() {
let type = ['works', 'testing'];
return type[Math.floor(Math.random() * type.length)];
}
function reset_works_interval() {
console.log(`Okay Working ${RANDOM_DATA}`);
}
function reset_testing_interval() {
console.log(`Testing also working ${RANDOM_DATA}`);
}
function reset_rantype() {
clearInterval(works_interval);
clearInterval(testing_interval);
if (get_random_ranType() === 'works') {
works_interval = setInterval(reset_works_interval, works_reset_period);
} else {
testing_interval = setInterval(reset_testing_interval, testing_reset_period);
}
}
setInterval(reset_random_data, random_data_reset_period); // But RANDOM DATA should update every 10 seconds - I have RANDON data
setInterval(reset_rantype, ranType_reset_period);

React clearInterval not working in class Component

I am trying to make a timer that will start at the beginning of the sorting visualization and run until sorting is over. The timer starts accordingly but does not stop after sorting. this works absolutely fine in functional Component (with useEffect hook) but does not work in class Component.
here is my startTimer function -
startTimer = () => {
let isAlgo = this.state.isAlgorithmSortOver;
let interval;
if (isAlgo === true) {
interval = setInterval(() => {
this.setState({
time: this.state.time + 10,
});
}, 10);
} else if (isAlgo === false) {
clearInterval(interval);
}
// return () => clearInterval(interval);
};
and here is startVisualizer function -
startVisualizer = () => {
let steps = this.state.arraySteps;
let colorSteps = this.state.colorSteps;
this.clearTimeouts();
let timeouts = [];
let i = 0;
while (i < steps.length - this.state.currentStep) {
let timeout = setTimeout(() => {
let currentStep = this.state.currentStep;
this.setState({
array: steps[currentStep],
colorElement: colorSteps[currentStep],
currentStep: currentStep + 1,
isAlgorithmSortOver: false,
});
//? comparing the currentStep with arraySteps and the state of isAlgorithmSortOver will remain false until the array is fully sorted.. Adding '+ 1' to currentStep because the arraySteps state always will be '+1' bigger than the currentStep..
if (currentStep + 1 === i) {
this.setState({
isAlgorithmSortOver: true,
});
}
timeouts.push(timeout);
}, this.state.delayAnimation * i);
i++;
}
this.startTimer();
this.setState({
timeouts: timeouts,
// isAlgorithmSortOver: false,
});
};
because you are not clearing the interval. Try to save interval's id to state like this:
startTimer = () => {
let isAlgo = this.state.isAlgorithmSortOver;
if (isAlgo === true) {
interval = setInterval(() => {
this.setState({
time: this.state.time + 10,
});
}, 10);
this.setState({interval})
}
};
Then you can then call clearInterval wherever you want, like this:
clearInterval(this.state.interval)
You also should bring out timeouts.push(timeout) from setTimeout where in while. Because, otherwise timeouts.push(timeout) does not work synchronously, it works after a while.

How to assign clearInterval function to the button which would stop the function started by another button?

As I understood from MDN, I am supposed to make variable and assign setInterval function to it, so that I could use that variable and call clearInterval for it, but for some reason, my code is now working. It is properly fetching data with buttonStart, but will not stop fetching data with buttonStop.
Thank you for your time.
const buttonStart = document.querySelector('#start')
const buttonStop = document.querySelector('#stop')
const list = document.querySelector('#list')
class Price {
constructor(time, price) {
this.time = time
this.price = price
}
}
const fetchBitcoin = async () => {
try {
const res = await fetch('https://api.cryptonator.com/api/ticker/btc-usd');
const data = await res.json();
const newPrice = new Price(data.timestamp, data.ticker.price)
return newPrice
} catch (e) {
console.log("Something went wrong in downloading price", e)
}
}
const addNewPrice = async () => {
const newLI = document.createElement('LI')
const newElement = await fetchBitcoin()
const newTime = convertTime(newElement.time)
newLI.append(newTime, ' ', newElement.price.slice(0, 8))
list.append(newLI)
}
function convertTime(time) {
let unix_timestamp = time
var date = new Date(unix_timestamp * 1000);
var hours = date.getHours();
var minutes = "0" + date.getMinutes();
var seconds = "0" + date.getSeconds();
var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
return formattedTime
}
let interval = buttonStart.addEventListener('click', () => {
setInterval(addNewPrice, 2000)
})
buttonStop.addEventListener('click', () => clearInterval(interval));
You need to create interval variable and assign the return value of the setInterval method rather than addEventListener because addEventListener does not return anything,
let interval;
buttonStart.addEventListener('click', () => {
interval = setInterval(addNewPrice, 2000)
})
You need to adjust the example below to your use case but this is what you need in general:
var timerEl = document.querySelector('.js-timer');
var startBtn = document.querySelector('.js-start');
var stopBtn = document.querySelector('.js-stop');
var intervalId;
var timer = 0;
startBtn.addEventListener('click', function() {
stopTimer();
console.log('start timer');
intervalId = setInterval(execTimer, 100);
});
stopBtn.addEventListener('click', stopTimer);
function stopTimer() {
timer = 0;
console.log('stop timer');
clearInterval(intervalId);
renderTimer();
}
function execTimer() {
timer++;
renderTimer();
console.log('timer score', timer);
}
function renderTimer() {
timerEl.textContent = timer;
}
<span class="js-timer"></span><br />
<button class="js-start">Start</button>
<button class="js-stop">Stop</button>

Can i call a action in every 20 second inside a timer which is always running in every second

I need to print a console in every 20 second(technically i will call a action in reactjs) inside a interval which is running in every second.
this is a dummy code not functioning properly.
var intervalDuration = 200;
var hitOnEvery = 20;
setInterval(() => {
interValDuration -= 1;
if (interValDuration >= 0) {
setTimeout(()=>{
console.log(interValDuration , 'Hit on every' + hitOnEvery + 'second')
},hitOnEvery);
}
console.log('This will print every '+intervalDuration +'count in a place')
}, 1000);
can someone correct and help me.
You can do it like this:
var interValDuration = 200;
var hitOnEvery = 20;
setInterval(() => {
interValDuration -= 1;
if (interValDuration % hitOnEvery == 0) {
console.log(interValDuration , 'Hit on every' + hitOnEvery + 'second')
}
console.log('This will print every '+interValDuration +'count in a place')
}, 1000);
Basically check if interValDuration divided by hitOnEvery has 0 leftover after division, meaning every 20sec perform action
Here is the closure function, for the generic usage
const timer = (() => {
let timer;
let seconds = 1;
return (func, hitAtTime) => {
let stopTimer = () => {
console.log(timer);
window.clearInterval(timer);
};
const startTimer = () => {
timer = window.setInterval(() => {
console.log("i run every second");
seconds++;
if (seconds % hitAtTime === 0) {
func();
}
}, 1000);
};
return {
stopTimer: stopTimer,
startTimer: startTimer,
};
};
})();
timer(() => console.log("i run every 10 seconds"), 10).startTimer();

Categories

Resources