How change variable from function setTimeout inside an loop - javascript

How alternate value to variable dinamic_delay using conditions described below?
var emails = []; // array
var number = 5;
var count = 0;
var dinamic_delay;
for (i = 0; i < emails.length; i++) {
count++;
if (count == number) {
dinamic_delay = 3000;
count = 0; // resset count
} else {
dinamic_delay = 500;
}
setTimeout(function (i) {
sendemail(email[i]);
}, dinamic_delay * i, i);
}

I had to remind myself how setTimeout works:
a. setTimeout(myfunction(), 5000) -calls the function after at least 5000 millisecs from now (when this code is executed)
b. setTimeout(myfunction(), 5000) -calls the function after at least 5000 millisecs from now (when this code is executed)
in other words there is not an automatic 10,000 millisec before b is called, e.g. might by 6000 ms
setInterval is useful if you want to call things at regular intervals.
The example below displays console.log message 3, 3, 3, 3, 10 seconds & repeats until the final email.
const bigDelay_c = 10000; //secs
const smallDelay_c = 3000; //secs
const totalEmails_c = 18; //total to process
var totalEmailsProcessed = 0; //running total
var timerId = 0;
timerId = setInterval(alertFunc, smallDelay_c);
function alertFunc() {
//sendEmail logic here
var currentdate = new Date();
totalEmailsProcessed++;
console.log(totalEmailsProcessed, currentdate.getHours() + ":" +
currentdate.getMinutes() + ":" + currentdate.getSeconds());
clearInterval(timerId); //stop interval repeating
//stop if all emails have been processed
if (totalEmailsProcessed >= totalEmails_c) {
console.log('all emails processed');
return;
}
//5th item in every 5 get bigDelay_c
if (totalEmailsProcessed % 5 == 4)
timerId = setInterval(alertFunc, bigDelay_c);
else
timerId = setInterval(alertFunc, smallDelay_c);
}

Related

How to process data after a counter reached to zero for a specific period of time, then the counter will start again after that peiod of time?

My scenario is that a node chooses a random number as a counter, then starts to auto-decrement the counter (I did this step). When the counter reaches to zero, then the node processes data for 1 minute only. After 1 minute of processing, the node will choose again a random number and auto-decrement it, then process the data for 1 minute. The node must do that repeatedly.
I have tried this:
var mqtt = require('mqtt')
var Broker_URL = 'mqtt://localhost';
var client = mqtt.connect(Broker_URL);
client.on('connect', function () {
console.log("MQTT connected "+ client.connected);
client.subscribe('DAG1');
})
var MIN_PER_RANK =3;
var MAX_PER_RANK =5;
function animateValue(start, end) {
if (start === end) return;
var current = start;
var increment = end > start? 1 : -1;
var timer = setInterval(function() {
current += increment;
if (current == end) {
clearInterval(timer);
}
console.log (current);
if (current === 0){
console.log("finish counter")
console.log("process data for 1 minute")
client.on('message', function (topic, message) {
processdata(topic, message)
})
}
}, 1000);
}
var randomvalue = Math.floor(Math.random() * (MAX_PER_RANK - MIN_PER_RANK + 1) + MIN_PER_RANK);
animateValue(randomvalue, 0);
var start = true;
setInterval(function(){
if(start){
start = false;
} else {
start = true;
console.log("start counter")
var randomvalue = Math.floor(Math.random() * (MAX_PER_RANK - MIN_PER_RANK + 1) + MIN_PER_RANK);
animateValue(randomvalue, 0);
}
}, 60000); //1 minute
function processdata(top, param) {
if (start){
console.log(param.toString())
}
}
The code is running in this way:
The node chooses a random number as a counter, starts to auto-decrement the counter. When node reaches to zero, it processes the data for 1 minute. Then, the node will sleep for another 1 minute. After that, the node will wake up and start the process again.
How to make the node starts a counter right away after 1 minute of process instead of getting to sleep?
How I could solve it?
Thanks in adavance
the output:
MQTT connected true
4
3
2
1
0
finish counter
process data for 1 minute
{"sensorvalue":"91","timestamp":1611236199874,"topicsensor":"sensor1","dataID":"0a9e9f87-51b4-4a37-91d5-773de6869491"}
{"sensorvalue":"99","timestamp":1611236214889,"topicsensor":"sensor1","dataID":"109bbf17-78b8-4357-90ac-ca23f760a4eb"}
start counter
3
2
1
0
finish counter
process data for 1 minute
{"sensorvalue":"80","timestamp":1611236219894,"topicsensor":"sensor1","dataID":"71398516-3757-4a0b-ad61-20e9a17891cc"}
{"sensorvalue":"80","timestamp":1611236219894,"topicsensor":"sensor1","dataID":"71398516-3757-4a0b-ad61-20e9a17891cc"}
Can be that what do you want.
var mqtt = require('mqtt')
var Broker_URL = 'mqtt://localhost';
var client = mqtt.connect(Broker_URL);
client.on('connect', function () {
console.log("MQTT connected " + client.connected);
client.subscribe('DAG1');
})
var MIN_PER_RANK = 3;
var MAX_PER_RANK = 5;
function animateValue(start, end) {
if (start === end) return;
var current = start;
var increment = end > start ? 1 : -1;
var timer = setInterval(function () {
current += increment;
console.log(current);
if (current == end) {
clearInterval(timer);
}
if (current === 0) {
console.log("finish counter")
console.log("process data for 1 minute")
client.on('message', function (topic, message) {
processdata(topic, message)
})
}
}, 1000);
}
function processdata(top, param) {
console.log(param.toString())
// ... do what do you want
animateValue(randomValue(), 0); // After all code inside processData() restart the function animateValue()
}
function randomValue() { // Generate a random number
return Math.floor(Math.random() * (MAX_PER_RANK - MIN_PER_RANK + 1) + MIN_PER_RANK);
}
animateValue(randomValue(), 0); // All start from here
I used the callback and recursive function.

HTML 5 Audio Player remaining time show delay

I have a problem with an audio player, when users press play the start-time timer is showing instantly, but remaining-time timer shows with a delay. I'm relatively new to JS, so I can not identify the problem on my own.
Can someone can help me with synching timers (start and remaining) show on play event?
CodePen
var isSeeking = false;
var seek = document.getElementById("seekObj");
var player = document.getElementById("player");
SetSeekColor();
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.split(".")[0],
temp_min = minutes.toString().length === 1 ? "0" + minutes : minutes,
temp_sec = seconds.toString().length === 1 ? "0" + seconds : seconds;
return temp_min + ":" + temp_sec;
}
function calculateCurrentValue(_seconds) {
function padTime(t) {
return t < 10 ? "0" + t : t;
}
if (typeof _seconds !== "number") return "";
if (_seconds < 0) {
_seconds = Math.abs(_seconds);
//console.log(_seconds);
}
var hours = Math.floor(_seconds / 3600),
minutes = Math.floor((_seconds % 3600) / 60),
seconds = Math.floor(_seconds % 60);
var hour = hours > 0 ? padTime(hours) + ":" : "";
return hour + padTime(minutes) + ":" + padTime(seconds);
}
function setupSeek() {
seek.max = player.duration;
}
function seekAudio() {
isSeeking = true;
player.currentTime = seek.value;
isSeeking = false;
}
var prevcurrentime = 0;
function initProgressBar() {
if (!isSeeking) {
seek.value = player.currentTime;
}
var length = player.duration;
var current_time = player.currentTime;
// calculate total length of value
var totalLength = calculateTotalValue(length);
// calculate current value time
var currentTime = calculateCurrentValue(current_time);
if (player.readyState === 4) {
jQuery(".end-time").html(totalLength);
jQuery(".start-time").html(currentTime);
}
//checking if the current time is bigger than the previous or else there will be sync different between remaining and current
if (currentTime > prevcurrentime) {
//calculate the remaining time
var rem_time = length - current_time;
jQuery(".rem-time").html(calculateCurrentValue(rem_time));
}
//setting the previouscurrent time to this current time
prevcurrentime = currentTime;
if (player.currentTime == player.duration) {
$("#play-btn").removeClass("pause");
}
}
function initPlayers(num) {
// pass num in if there are multiple audio players e.g 'player' + i
for (var i = 0; i < num; i++) {
(function() {
// Variables
// ----------------------------------------------------------
// audio embed object
var playerContainer = document.getElementById("player-container"),
player = document.getElementById("player"),
isPlaying = false,
playBtn = document.getElementById("play-btn");
// Controls Listeners
// ----------------------------------------------------------
if (playBtn != null) {
playBtn.addEventListener("click", function() {
togglePlay();
});
}
// Controls & Sounds Methods
// ----------------------------------------------------------
function togglePlay() {
if (player.paused === false) {
player.pause();
isPlaying = false;
$("#play-btn").removeClass("pause");
} else {
$(".start-time").html("");
player.play();
$("#play-btn").addClass("pause");
isPlaying = true;
}
}
})();
}
}
looking good, this is an error in the html. In this piece of code just replace the class rem-time by end-time.
<small style="float: right; position: relative; right: 21px;" class="end-time" onclick="showhideRemaining(this)"></small>
I think the root of your problem lies within the performance of your code. I can't see a big time difference between the two counters, but here are some suggested improvements:
You have the padTime function, so use it (see point 2)!
function padTime(t) {
return t < 10 ? "0" + t : t;
}
no unnecessary or early conversion to strings:
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60);
var seconds = Math.floor(length - minutes * 60);
// use the padTime function here with numbers
return padTime(minutes) + ":" + padTime(seconds);
}
do not query the elements over and over again:
if (player.readyState === 4) {
jQuery(".end-time").html(totalLength);
jQuery(".start-time").html(currentTime);
}
Here, instead of querying the elements (jQuery(".end-time")) every time in your ontimeupdate callback, save the references in variables outside of the callback function.
limit color updates.
setInterval(function() {
SetSeekColor();
}, 34);
Updating the color every millisecond is just overkill. 34 milliseconds should equal something around 30fps.
I noticed you have are planning to have multiple players on one page (initPlayers(num)). Here a few thoughts:
When you initialise the players, save each single player with its UI elements in an Object
initPlayers(jQuery("#player-container").length);: IDs are (must be) unique in an entire HTML Document. This wont work, change it to a class.

Modify Countup Timer To Include Currency Formatting In Javascript

I have a simple countup timer that takes a starting number and randomly counts up. However, it doesn't work correctly on numbers that include decimals and commas.
How can I modify this to count up correctly in cents?
For example I want to count starting at the number 1,234,567.15 and every 500 milliseconds it adds a random amount of cents to the end. Then when it goes over 99 it adds to the dollar value.
Current Usage:
<span>$</span><span id="counter">1,234,567.15</span>
Javascript:
<script>
var timer;
function startCount() {
timer = setInterval(count, 500); // 200 = 200ms delay between counter changes. Lower num = faster, Bigger = slower.
}
function count() {
var do_wait = Math.ceil(4 * Math.random());
if (do_wait == 4) {
var rand_no = Math.ceil(4 * Math.random()); // 4 = random decrement amount. Counter will decrease anywhere from 1 - 4.
var el = document.getElementById('counter');
var currentNumber = parseFloat(el.innerHTML);
var newNumber = currentNumber + rand_no;
if (newNumber < 99999999999) {
el.innerHTML = newNumber;
}
}
}
startCount();
</script>
parseFloat doesn't process ',' ,it will stop parse will met ',';
the best way is to use newNumber.toLocaleString()
var timer;
function startCount() {
timer = setInterval(count, 500); // 200 = 200ms delay between counter changes. Lower num = faster, Bigger = slower.
}
function count() {
var do_wait = Math.ceil(4 * Math.random());
if (do_wait == 4) {
// var rand_no = Math.ceil(4 * Math.random()); // 4 = random decrement amount. Counter will decrease anywhere from 1 - 4.
var rand_no = 4 * Math.random(); //if you also want cents change,take this and comment previous line
var el = document.getElementById('counter');
var currentNumber = parseFloat(el.innerHTML.replace(/,/g, ''));
var newNumber = currentNumber + rand_no;
if (newNumber < 99999999999) {
el.innerHTML = Number(newNumber.toFixed(2)).toLocaleString();
}
}
}
startCount();
<span>$</span><span id="counter">1,234,567.15</span>
if not work ,process it manually:
replace ',' to '' and calculate the number and add ',' back:
var timer;
function startCount() {
timer = setInterval(count, 500); // 200 = 200ms delay between counter changes. Lower num = faster, Bigger = slower.
}
function count() {
var do_wait = Math.ceil(4 * Math.random());
if (do_wait == 4) {
// var rand_no = Math.ceil(4 * Math.random()); // 4 = random decrement amount. Counter will decrease anywhere from 1 - 4.
var rand_no = 4 * Math.random(); //if you also want cents change,take this and comment previous line
var el = document.getElementById('counter');
var currentNumber = parseFloat(el.innerHTML.replace(/,/g, ''));
var newNumber = currentNumber + rand_no;
if (newNumber < 99999999999) {
el.innerHTML = processNumber(newNumber);
}
}
function processNumber(num) {
let strArr = num.toFixed(2).split('.')[0].split(/|/g).reverse();
let result = strArr.map(function(v, index) {
return index % 3 === 0 ? v + ',' : v;
}).reverse();
return result.join('').replace(/,$/, '.') + num.toFixed(2).split('.')[1];
}
}
startCount();
<span>$</span><span id="counter">1,234,567.15</span>

Trying to get timer to start once arrived on the page

I made the following fiddle of what I have right now..
https://jsfiddle.net/r5yj99bs/1/
I'm trying to start right when I get onto a page, but allowing the option to leave the pause/resume option. Then is there anyway to display the remaining time as '5 minutes' instead of '300 seconds' and then count down that way rather than only seconds.
<button class="start-pause">Start</button>
<h2 class="time-left"></h2>
var times = [];
var counter_interval;
var $time_left = $('.time-left');
var $button = $('.start-pause');
// timer length in seconds
var timer_length = 300;
$('body').on('click', '.start-pause', function() {
// are we starting or stopping?
var starting = times.length % 2 == 0;
times.push(Date.now());
if (starting) {
$button.html('Pause');
counter_interval = setInterval(function() {
var time_left = Math.floor(timer_length - sum_elapsed());
if (time_left < 1) {
clearInterval(counter_interval);
return finished();
}
$time_left.html(time_left);
}, 100);
} else {
$button.html('Resume');
clearInterval(counter_interval);
}
});
var sum_elapsed = function() {
sum = 0;
for (var i=0; i<times.length; i++) {
if (i % 2 == 1) {
sum += (times[i] - times[i-1]);
}
if (i == (times.length - 1)) {
sum += (Date.now() - times[i]);
}
}
// convert milliseconds to seconds
return sum / 1000;
};
var finished = function() {
$button.attr('disabled','disabled').html('Finished');
$time_left.html("Time's Up");
};
There is a good time module called moment. You can get it through npm or from moments.com
That can format relative time to human readable strings.
If you want to do it yourself, take the seconds modulus 60 to get the minutes. Using modulus you can extract all info about hours and so on.
You may change the following line:
$time_left.html(time_left);
to:
$time_left.html(secToMinTxt(time_left));
and add the following functions:
function pad(num) {
var str = "" + num;
var pad = "00";
return pad.substring(0, pad.length - str.length) + str;
}
function secToMinTxt(seconds) {
var min = Math.floor(seconds / 60);
var sec = seconds % 60;
return pad(min) + ":" + pad(sec);
}
JSFiddle reference : https://jsfiddle.net/r5yj99bs/2/
If interpret Question correctly, try using Math.round with argument existing time_left variable divided by 60
var time_left = Math.round(Math.floor(timer_length - sum_elapsed()) / 60);
jsfiddle https://jsfiddle.net/r5yj99bs/3/

Howto run function every few seconds that has return values?

How can I run this every few second , without blocking the rest of the pagefrom loading.
function Create() {
var SomeArray = [];
for ( var i=0; i<=1 ; i ++) {
SomeArray[i] = (Math.random() * 10) + 1;
//alert(arr[0]);
}
return SomeArray;
}
var x = Create();
alert(x[0] + x[1]);
I was trying this var timer = setInterval(Create, 5000); it prevent loading rest of the page.
i want to get new values every few seconds
A basic example would be:
var counter = 0;
var timerRef;
var increment = function() {
counter += 1;
console.log(counter);
timerRef = setTimeout(increment, 1000);
}
setTimeout(increment, 1000);
// clearTimeout(timerRef);
Please avoid document.write refer the screencast for further details.
setInterval() can be configured to repeatedly call any function you designate at whatever time interval you request. But, you can't retrieve a return value from that function. Instead, you need to process the results from within the callback that you pass to setInterval() or call some other function and pass the results you generate inside the callback. This is how asynchronous functions work in JavaScript. I've provided several examples below of your options:
If you just want to generate two random decimal values between 1 and 10 (inclusive) every 5 seconds, you can do that like this:
var interval = setInterval(function() {
var rand1 = (Math.random() * 10) + 1;
var rand2 = (Math.random() * 10) + 1;
// now insert code here to do something with the two random numbers
}, 5000);
If you wanted the random values to be integers (which is more common), then you would do this:
var interval = setInterval(function() {
var rand1 = Math.floor(Math.random() * 10) + 1;
var rand2 = Math.floor(Math.random() * 10) + 1;
// now insert code here to do something with the two random numbers
}, 5000);
If you want to call a function and pass it those two random numbers, you can do this:
function processRandoms(r1, r2) {
// code here to do something with the two random numbers
}
var interval = setInterval(function() {
var rand1 = Math.floor(Math.random() * 10) + 1;
var rand2 = Math.floor(Math.random() * 10) + 1;
processRandoms(rand1, rand2);
}, 5000);
You can then stop the recurring interval at any time with this:
clearInterval(interval);

Categories

Resources