JavaScript setInterval and setTimeout provide inconsistent timing - timer

I am attempting to show 1 element at a time with a total of 3 elements. Each element fades in for 1 second, pauses for 2 seconds, then fades outs for 1 second. Thus, for all 3 elements, the total interval is 12 seconds (3 elements X 4 seconds each).
At first, everything appears to be working fine, but after a few intervals or so, the timing is inconsistent, and multiple elements will show at once.
Consequently, I have attempted to resolve my issue by searching for similar or equivalent questions to mine, and I have tried different methods (such as giving 1 second gap between element changes), but I get the same undesired results.
Any assistance is appreciated!
/**
* Stocks (Nasdaq, S&P 500, and Dow) —— Interval
* —————————————————————————————————————————————
*/
$(document).ready(function()
{
// Initialize stock HTML elements as variables
const nasdaq = $(".stocks .nasdaq");
const sp500 = $(".stocks .sp_500");
const dow = $(".stocks .dow");
// Hide all stock HTML elements upon DOM load (except Nasdaq)
nasdaq.show();
sp500.hide();
dow.hide();
// Run once before interval begins [00:00 —— 00:04]
nasdaq.delay(2000).fadeOut(1000);
// Run once before interval begins [00:04 —— 00:08]
sp500.delay(4000).fadeIn(1000).delay(2000).fadeOut(1000);
// Run once before interval begins [00:08 —— 00:12]
dow.delay(8000).fadeIn(1000).delay(2000).fadeOut(1000);
// Run interval for a every 12 seconds (4-second span per each stock)
setInterval(function() {
nasdaq.fadeIn(1000);
// Pause for 2 seconds before fading out
setTimeout(function() {
nasdaq.fadeOut(1000);
}, 3000);
// Pause for 2 seconds before fading in
setTimeout(function() {
sp500.fadeIn(1000);
}, 4000);
// Pause for 2 seconds before fading out
setTimeout(function() {
sp500.fadeOut(1000);
}, 6000);
// Pause for 2 seconds before fading in
setTimeout(function() {
dow.fadeIn(1000);
}, 8000);
// Pause for 2 seconds before fading out
setTimeout(function() {
dow.fadeOut(1000);
}, 10000);
}, 12000);
});
Additionally, I tried removing the setTimeout() function & used 3 setInterval() functions along with the delay() function that run at the same time, but I get the same undesired results.
// Run interval for a 4-second span every 12 seconds
setInterval(function() {
nasdaq.fadeIn(1000).delay(2000).fadeOut(1000);
}, 12000);
// Run interval for a 4-second span every 12 seconds
setInterval(function() {
sp500.delay(4000).fadeIn(1000).delay(2000).fadeOut(1000);
}, 12000);
// Run interval for a 4-second span every 12 seconds
setInterval(function() {
dow.delay(8000).fadeIn(1000).delay(2000).fadeOut(1000);
}, 12000);
UPDATE (CSS #keyframes solution): I know this may not be a solution for all situations that require an interval, but I created the desired results I'm seeking by using the #keyframes. Here's a CopePen example.

Related

How to use setInterval and setTimeout with React hooks

I want to loop through an array of strings
When a new string, from the array, is selected I want to print out a
substring of the selected string every 0.1 second
After the entire string is printed I want to pause and then select the
next string in the array
Repeat
eg ['one', 'two']
output:
o
on
one
// pause 1 second
t
tw
two
// pause 1 second
o
on
one
// pause 1 second
I have tried this but it only loops through once
useEffect(() => {
let i = 0
function increment() {
i++
console.log(i)
}
const incrementTimer = setInterval(increment, 100)
setInterval(() => {
clearInterval(incrementTimer)
}, 1000)
}, [])
I created a codesandbox link: https://codesandbox.io/s/recursing-bash-hkmqrc?file=/src/App.js
This is done by rxjs as you are dealing with time related actions. rxjs is the best tool. After you reload the page, it will start to log values as you expect in 1s.
Can you please let me know if the result is what you want? Thanks.

How to execute function based on an interval of 5 seconds after the function was last called?

I have a function(testFunction) in my controller that gets called (by callFunction) a random number of times in a random space of time. So for example, callFunction could call testFunction 10 times; waits 30 seconds; and then calls testFunction 20 times; waits 24 hours and then calls the testFunction 2 times, etc.... I would like to execute another function 5 seconds after the last instance of that function call. For example:
vm.testFunction = () => {
console.log("a");
if(some conditional statement that determines that it's been five seconds since this function was last called)
{
console.log("b");
callTestFunction2();
}
}
A problem input:
callFunction() calls testFunction 2 times; waits 30 seconds; calls
testFunction 3 times; waits 2 seconds; calls testFunction 10 times:
The answer should be
aabaaaaaaaaaaaaab
It sounds like you'll want to use $interval or $timeout
$timeout docs and $interval docs
If you wanted to call callTestFunction2() after 5 seconds it would look like this
vm.testFunction = () => {
console.log("a");
$timeout(function() {
console.log("b");
callTestFunction2();
}, 5000); // Delay is in milliseconds 5 secs = 5000
}

in angularjs, With time, $interval delay is reducing automatically. would it be an issue by having multiple $intervals in single controller?

I have an AngularJs app. in a single controller, i have to pull data from 3 different source and display the data in 3 different sections. (in top , mid and bottom section). data in each section would vary in a set delay. for top section, i have used Set interval and clear interval. for mid and bottom section , i have used $interval.For mid section, the delay is set to 7 and for bottom section, it is set to 10 sec.
when i launch the application, everything works fine. but with time, the mid and bottom section varies in every 2 or 3 seconds instead of 7 and 10 respectively. i dont know where i am doing the mistake. i have not added $interval.cancel as i want the mid and bottom section to bring the data in 7 and 10 sec delay continuously without stopping. i am also using socket to bring the data for all the sections. I have not used $scope.on'Destory' . i don't if that has any impact here. below is the code. Any help would be greatly appreciated.
socket.on('midsection', function (data) {
tableJson = [];
SplicedJson = [];
jsoninput = [];
jsoninput.push(data);
// splitting single array in to two array's so that we can display them one after the other after some delay
SplicedJson.push(jsoninput[0].splice(0, 6));
tableJson.push(jsoninput[0]);
$scope.tableData = tableJson;
//Creating interval and setting counter just to swap the json source for display
var Counter = 1;
$interval(function () {
Counter++;
if (Counter % 2 === 0) {
$scope.tableData = SplicedJson;
}
else {
$scope.tableData = tableJson;
}
}, 7000);
});
socket.on('lastSection', function (data) {
if (data.length > 3) {
array1.push(data[0]["publisher"]);
array1.push(data[1]["publisher"]);
array1.push(data[2]["publisher"]);
array2.push(data[0]["title"]);
array2.push(data[1]["title"]);
array2.push(data[2]["title"]);
$scope.msg = array1;
$scope.msg2 = array2;
$interval(function () {
data = shuffle(data); // caling custom built shuffle fn to shuffle the data to display random data everytime
console.log('Shuffled', data);
array1= [];
array2= [];
array1.push(data[0]["publisher"]);
array1.push(data[1]["publisher"]);
array1.push(data[2]["publisher"]);
array2.push(data[0]["title"]);
array2.push(data[1]["title"]);
array2.push(data[2]["title"]);
$scope.msg = array1;
$scope.msg2 = array2;
},10000);
}
});
Code # connection launch is below
io.on('connection', function (socket) {
socket.join(socket.handshake.query.room)
var entExFilepath = './midsectionData.json';
var parsedJSON = JSON.parse(fs.readFileSync(entExFilepath, 'utf8'));
fs.watchFile(entExFilepath, function () {
parsedJSON = JSON.parse(fs.readFileSync(entExFilepath, 'utf8'));
io.sockets.emit('midsection', parsedJSON);
});
io.sockets.emit('midsection', parsedJSON);
if (feedresults.length > 3) {
io.sockets.emit('lastsection', feedresults);
}
I found the cause for this issue. the problem was when i send the data for mid and last section, i was doing socket.emit which was equivalent to broadcasting the answer to all the clients.So Whenever a new request comes to the server, socket.emit was being called and sent the data to the client. (which means it also calls the internal block when ever a new request comes. so the interval is called again and again).I should have done like below. This resolved the issue.
//io.sockets.emit('lastsection', feedresults);
io.sockets.in(socket.handshake.query.room).emit('lastsection', feedresults);// This should send the data to the current client
Hope this helps others

OpenLayers loop layers function

In OpenLayers, I have a button (show), when I press on it, I got a layer on the map
My question: How can I show many layers consequently With a certain frame rate
(Something like a loop!)
to show a new/other layer every X seconds, use setInterval
let's assume that you somehow got an array of dates for which you have tiles, and a function displayLayerByDate(dateObject) that can show the layer.
function animatedLayers(arrayOfDates) {
let currentIdx = 0;
const handle = setInterval(function() {
const currentDate = arrayOfDates[currentIdx];
displayLayerByDate(dateObject);
}, 5000);
}

Angular JS cancel a debounce function after one itration

I saw in a tutorial a debounce function made for angular js. It works well (but I do not understand the code very well).
The questions are:
Can you explain how this debounce works?
How can I reset the debounce function after it has worked one time?
function debounce(callback, interval) {
var timeout = null;
return function() {
$timeout.cancel(timeout);
timeout = $timeout(callback, interval);
};
};
inputNgEl.bind('keydown keypress', debounce(function () {
el.toggleClass('has-error', formCtrl[inputName].$invalid);
el.toggleClass('has-success', formCtrl[inputName].$valid);
}, 1000));
Can you explain how this debounce works?
The debounce(callback, 1000) returns a new function. So this inputNgEl.bind('keydown keypress',debounce(callback, 1000)) attaches function returned from debounce as event handler inputNgEl.
When events happen the attached event handler function is called possibly many times in row which results in:
time (in 100ms): 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
keepresses : ↓ ↓ ↓
time to fire : 10 9 8 10 9 8 7 6 5 4 3 2 1 ✦ 10 9
callback
(in 100ms)
So when the event handler (returned from debounce) is called timeout variable is null. Calling $timeout.cancel(null) does nothing. Next we schedule the callback function to be executed after 1000 ms using $timeout service call. The call returns a promise that will be resolved after the given timeout (1000ms) elapses.
Now on second call to event handler the timeout variable has a promise so we cancel it - the callback function wont be called. Next we immediately schedule callback function again to be executed after 1000 ms and store a new promise inside timeout variable.
How can I reset the debounce function after it has worked one time?
I'm not sure what you mean by reseting the function? Immediately after callback is called the debounce function state and behaviour is almost identical to initial state - except for timeout variable.
If you would like to remove the debounce effect after the the callback is called for the first time you could do something like:
function debounce(callback, interval) {
var timeout = null;
var inner = function() {
$timeout.cancel(timeout);
if(inner.interval){
timeout = $timeout(function(){
callback();
inner.interval = null;
}, interval);
} else {
callback();
}
};
inner.interval = interval;
return inner;
};
Which basically after first timeout elapses will switch to calling callback immediately.

Resources