I'm making a little clock using getTime(), but the output won't refresh. I have tried this:
<p id="clock"></p>
var i;
for (i=0; i < 5; i++){
var date = getTime;
var time = time.getHour() + ":" + time.getMinute() + ":" + time.getSecond()
getElementById('clock').innerHTML = time;
}
Though it just keeps my tab in a constant state of loading. How do I fix this? Thanks!
Just move your code inside setInterval()
let i = 5;
const timer = setInterval(() => {
var date = getTime;
var time = time.getHour() + ":" + time.getMinute() + ":" + time.getSecond()
getElementById('clock').innerHTML = time;
i--;
if (i < 0) {
clearInterval(timer)
}
}, 1000);
So setInterval() lets your code run asyncrounously, that means it doesnt block the rest of the execution, because it runs "seperately" (I would like to describe it better, but my english skills are lacking).
setInterval runs your code every 1000 ms (as specified) forever, unless you dont clear it with clearInterval(). If you want to make a timer it is quiet useful.
this () => {} is an arrow function. You can also use function(){}, if you want, in this case it makes no difference.
Here is the w3schools reference for setInterval(): https://www.w3schools.com/jsref/met_win_setinterval.asp
and here is the MDN reference to asynchronous javascript: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous
Good luck with your project ;)
I hope this helps
setInterval (function refresh(){
var fecha = new Date();
var hora = fecha.getHours();
var minutos = fecha.getMinutes();
var segundos = fecha.getSeconds();
var textoHora = `
${hora}:${minutos}:${segundos}
`;
document.getElementById('clock').innerHTML = textoHora;
}, 1000);
Related
I have to do a timer in javascript with timing events, the time units should be in milliseconds.
i need something like this:
start_timer
//some code..
stop_timer
//and then show the ms
sorry for my english, and thank you for help!
edit:
i tried this method as test:
var d = new Date();
var time = d.toLocaleTimeString();
var myVar = window.setInterval(function(time){ time -= d.toLocaleTimeString()
return code.value = time.toString();
}, 5000);
The console.time method is perfect but if you want to keep the result in memory you have to use the Date.now method.
let now = Date.now();
for (let i = 0; i < 100000; ++i)
// ...
// Result in milliseconds.
let result = Date.now() - now;
// If you want to show it in a input box.
input.value = result + "ms";
You can use console.time(), for the browsers that support it:
console.time('Stuff')
for (var i = 0; i < 1000; i++) {
// run some code
}
console.timeEnd('Stuff')
setTimeout(func,delay) seems to fire very precisely at the specified time, as long as the page is not running some script while it is trying to fire the function. But is there a way to take lag into account?
For example if I set a 3sec timeout and javascript runs some heavy code which makes the page leggy for a while. As long as processing the "heavy code" is done by the 3sec it will timeout after ~3sec.
Is there a way to take the "heavy code" processing time into account and timeout after 3sec + the time the page was blocked?
Here is a jsfiddle: http://jsfiddle.net/me2loveit2/mCj2J/
var timeStart = new Date().getTime();
setTimeout(test, 3000); //<-- timeout should be 100
function test() {
var timeAfter100MS = new Date().getTime();
$('body').append('Timeout Fired at: <br>' + (timeAfter100MS - timeStart) + 'ms<br> (should be ~3000, but it did not take the blocked time into account.)');
}
function block() {
for (var i = 0; i < 100000000; i++) {};
}
block();
block();
block();
var timeEnd = new Date().getTime();
$('body').append('Page was blocked(running importaint code :)) for:<br>' + (timeEnd - timeStart) + 'ms<br>');
As #adeneo pointed out, there is no such possibility. You simply can't know how effectively processor is running your code at the other end, or the tasks it is currently making which might slow it down further. Every case is different. setTimeout tries to match the specified time but very often, it just can't be exact.
I think the solution is just to change your mindset. Try to avoid long blocking synchronous operations such as for (var i = 0; i < 10000000; i++) {}; When you drop or modify these you can have more accurate setTimeout firing. The reason being, that there will be smaller executable chunks in the event queue.
Generally speaking, there are different ways to do processing of blocking events. For instance, you could look into Web workers or yielding setTimeout calls. (See links at the end of this post).
Hence, I don't know your specific case, but if you are trying to make many setTimeout calls just as in game programming (loops) solution is to try to alter future setTimeout calls to contain smaller value so the full loop will try to catch up the simulation to match the specific frame rate.
This is usually done with combination of requestAnimationFrame.
Short example of a loop which attemps to run 30 fps in the browser:
You can also view it in js fiddle
/**
* This is example to run loop with 30fps in the browser
*
*/
var gl = {
now: new Date().getTime(),
dt: 0.0,
last: new Date().getTime(),
// physics with 0.033333 steps
step: 1 / 30
},
frames = 0,
started = new Date().getTime();
/**
* Game loop
*
*/
var gameLoop = function () {
gl.now = new Date().getTime();
gl.dt = gl.dt + Math.min(1, (gl.now - gl.last) / 1000);
while (gl.dt > gl.step) {
gl.dt = gl.dt - gl.step;
// Increase frames
frames++;
if(frames === 30) {
// How long it took to execute 30 frames in 1000 ms ?
document.body.innerHTML = "We executed 30 frames in " + (new Date().getTime() - started) + " ms.";
started = new Date().getTime();
frames = 0;
}
}
// last
gl.last = gl.now;
// next
requestAnimationFrame(gameLoop);
};
// Start the game loop
gameLoop();
Hopefully, this gave you some ideas. Thus, don't forget to use css transitions and similar when those can be applied.
For further reading, I recommend:
Yielding setTimeout calls
How to avoid blocking the browser while doing heavy work
Using Web Workers
Cheers.
Not sure I understand the question 100%, but if you do something like this, you're able to see if the other stuff (heavy processing) is not done by the time the timeout runs. This should take about 5 seconds, if you switch the 2000000000 to a 20000 (less proccessing), it should come back at 3 seconds.
var timeStart = new Date().getTime();
setTimeout(test, 3000); //<-- timeout should be 100
var currentTime = new Date().getTime();
function test() {
if (currentTime - timeStart < 3000){
var timeAfter100MS = new Date().getTime();
$('body').append('Took less than 3 seconds - ' + (timeAfter100MS - timeStart)+"ms");
}else{
$('body').append('Took more than 3 seconds');
}
}
function block() {
for (var i = 0; i < 10000000; i++) {};
currentTime = new Date().getTime();
}
block();
block();
block();
var timeEnd = new Date().getTime();
$('body').append('Page was blocked(running importaint code :)) for:<br>' + (timeEnd - timeStart) + 'ms<br>');
If the 'important' code causes really significant lag, and precise timing is important, you can keep the precision by using two timeouts. The first timeout measures the lag and sets the second timeout accordingly.
Here's an example, using your code as a basis:
var timeStart = new Date().getTime();
var msDelay = 3000;
setTimeout(testLag, msDelay - 500);
function testLag() {
var timeTestLag = new Date().getTime();
$('body').append('testLag() fired at: ' + (timeTestLag - timeStart) + 'ms<br/>');
setTimeout(test, timeStart + msDelay - timeTestLag);
}
function test() {
var timeAfter100MS = new Date().getTime();
$('body').append('Timeout Fired at: <br>' + (timeAfter100MS - timeStart) + 'ms<br> (should be ~3000, but it did not take the blocked time into account.)');
}
function block() {
for (var i = 0; i < 1000000000; i++) {};
}
block();
block();
block();
block();
block();
var timeEnd = new Date().getTime();
$('body').append('Page was blocked(running importaint code :)) for:<br>' + (timeEnd - timeStart) + 'ms<br>');
Note that the block is significantly more intensive than yours - I added a zero to your 100000000, and added a couple of extra block() calls. You might need to adjust the figures to get a sensible level of block for your own machine.
Based on Mauno's Answer I came up with a solution to temporarily "track the lag" using an interval. I am setting an interval with short intervals to capture the delay and set another timeout if necessary. Here is the working example: http://jsfiddle.net/me2loveit2/mCj2J/14/
It is approximate, but always walls within 100ms of the target which is good enough for me. It could be even more accurate if I increase the interval rate, but what I got is good enough for me.
I know using timeout & interval is not the best but sometimes the only way. I am just using them for a couple of seconds on page load and that's it.
Here is the code:
var timeStart = new Date().getTime();
var aditionalTimeout = 0;
var myTimeout;
setTimer(3000);
block();
block();
block();
var timeEnd = new Date().getTime();
$('body').append('Page was blocked(running importaint code :)) for:<br>' + (timeEnd - timeStart) + 'ms<br>');
function setTimer(milliseconds) {
//allow additional time to account for the huge lag the page has on load
recoverLagTime(milliseconds);
myTimeout = setTimeout(function () {
if (!aditionalTimeout) {
test();
} else {
if (aditionalTimeout >= milliseconds) {
test();
return;
}
setTimer(aditionalTimeout);
}
}, milliseconds);
}
function recoverLagTime(timeoutTime) {
aditionalTimeout = 0;
var interval = 50;
var counter = Math.ceil(timeoutTime / interval);
var startTime = new Date().getTime();
var intervalTime;
var lagInterval = setInterval(adjustTimer, interval);
function adjustTimer() {
if (counter <= 0 || aditionalTimeout < 0) {
clearInterval(lagInterval);
return;
}
counter--;
intervalTime = new Date().getTime();
var diff = (intervalTime - startTime);
if (diff > (interval + 5)) {
aditionalTimeout += (diff - interval);
}
startTime = new Date().getTime();
}
}
function test() {
aditionalTimeout = -100;//stop the check function
var timeAfter100MS = new Date().getTime();
$('body').append('Timeout Fired at: <br>' + (timeAfter100MS - timeStart) + 'ms<br> (should be ~3000 + ~amount blocked)');
}
function block() {
for (var i = 0; i < 100000000; i++) {};
}
I wrote a small (2-file) library for exactly these purposes : running heavy code whenever the CPU has idle time (using requestAnimationFrame) by splitting the code into smaller iterations so it doesn't block the whole application by allotting a specific percentage of CPU time to execution the code, and use the remainder to execute other scripts / update UI.
It functions similarly to other answers, but might be convenient to you as you can easily calculate elapsed time between executions, if you need to know these figures (or use it to leverage operations within your application, as that's what it was written for)
https://github.com/igorski/zThreader
Trying to make a simple count up timer in jQuery... this sort of works but is adding the numbers to the end of '0000' and I want it to go '0001' '0002' '0003' etc...
This is all happening in the jQuery onReady scope.
var i = '0000'
var timer = function doSomething ( )
{
i = i+= 1
$('.counter').text(i);
console.log(i);
}
setInterval (timer, 1000 );
Your "i" variable needs to be an integer. You can format it how you like when you want to print it somewhere.
$(document).ready(function() {
var i = 0;
var target = $('.counter');
var timer = function doSomething ( )
{
i++;
var output = pad(i,4);
target.text(output);
console.log(output);
}
setInterval (timer, 1000 );
});
function pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}
Your current code is appending to a string, not addition to a number. It essentially looks like
i = '0000' + 1, i = '00001' + 1, i = '000011' + 1 ...
and so on. You'll need to keep it integer based to continue adding to the number. Here's an example with the formatting it looks like you wanted.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
http://jsfiddle.net/jDaTK/
I would do something more like this:
// Make sure Date.now exists in your environment
Date.now = Date.now || function () { return Number(new Date()); };
var time = 0,
start = Date.now(),
intervalId;
intervalId = setInterval(function () {
var seconds, display;
// get the exact time since the timer was started
time = Date.now() - start;
// get the number or seconds, rounded down
seconds = Math.floor(time / 1000);
display = '' + seconds;
// pad the beginning of your display string with zeros
while (display.length < 4) {
display = "0" + display;
}
console.log(display);
}, 100);
setInterval is not exact. This code ensures that while the display could be up to nearly a second off (in theory), the actual time you are tracking is always the exact amount of time that has elapsed since you started the timer. But this code would update the display about once every tenth of a second, so it's not likely to ever be off more than a few milliseconds.
From here you can figure out smarter ways to update the display to ensure you have the level of accuracy you need. If this needs to be pretty accurate, then you could make sure you are displaying to the tenth of the second.
I really recommend the jQuery CountUp plugin. I tried a number of Javascript counters and this was one of the easiest to implement and came with lots of goodies:
<script type="text/javascript">
$(document).ready(function(){
$('#counter').countUp({
'lang':'en', 'format':'full', 'sinceDate': '22/07/2008-00::00';
});
});
</script>
<div id="counter"></div>
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.
Thanks Sean for your help. I have moved the calculation code to its own method as you suggested. After debugging I have realised the problem is something to do with storing values globally. I think I have accidently created closures. I have moved the calculation code into a method named calculate() that is run once so that the values of the variable are set globally. but while the method is running the correct values are set, as soon as the method exits and the move() method is called all the values are set to undefined or 0. In the calculate method I even used a hidden field to set the value ('mills') so that I can pass the interval time to this testTimer = window.setInterval(move,document.getElementById('mills').value,"testTimer"); Code of thecalculate()` method looks like this:-
var duration_equiv_seconds = 0;
var duration_equiv_millsec = 0;
var elapsed_percentage = 0;
var elapsed = 0;
var duration = 0;
// function in one JS file
function calculate () {
duration = document.getElementById('callDuration').value;
elapsed = document.getElementById('callElapsed').value;
duration_equiv_seconds = duration/100;
duration_equiv_millsec = duration_equiv_seconds * 1000;
document.getElementById('mills').value = Number(duration)/100 * 1000 ;
elapsed_percentage = (elapsed/duration) * 100;
display_progress(elapsed_percentage);
var countCalc = 0;
document.getElementById('status_message').innerHTML =" CountCalc = " + countCalc + " duration = " + duration + " elapsed =" + elapsed + " elapsed2Var =" + elapsed2Var +" duration_equiv_seconds = " + duration_equiv_seconds + " duration_equiv_millsec=" + duration_equiv_millsec + "
elapsed_percentage=" + elapsed_percentage; countCalc++; return duration_equiv_millsec; }
function voice_progress (time_interval){
// outer timer
voiceTimer = window.setInterval(function(){
handleDurationElapsedRequest()
// outside
function move(){
var count = 0;
duration = document.getElementById('callDuration').value;
elapsed = document.getElementById('callElapsed').value;
duration_equiv_seconds = duration/100;
duration_equiv_millsec = duration_equiv_seconds * 1000;
elapsed = Number(elapsed) + Number(duration_equiv_seconds);
elapsed_percentage = (elapsed/duration) * 100;
document.getElementById('callElapsed').value = elapsed;
display_progress(elapsed_percentage);
move_bar(elapsed_percentage);
if (elapsed_percentage >= 100){
terminate_timer(testTimer);
}
document.getElementById('status_message').innerHTML =" at the endAt the end" + count + " duration = " + duration + " elapsed =" + elapsed +" duration_equiv_seconds = " + duration_equiv_seconds + " duration_equiv_millsec=" + duration_equiv_millsec + " elapsed_percentage=" + elapsed_percentage;
count++;
return duration_equiv_millsec;
}
var sleepTime = calculate(); // sleep time returns 0
testTimer = window.setInterval(move,document.getElementById('mills').value ,"testTimer");
},time_interval,"voiceTimer"); // end of outer Timer (time_interval = 1500) called from <body onload="voice_progress(1500);">
}
//.................................................................`enter code here`
// in another JS file
// XMLHttpObject is created called, server returns the correct values
function handleDurationElapsedRequest(){
if(xmlHttpObject.readyState==4){
if(xmlHttpObject.status==200){
var resp = xmlHttpObject.responseText;
var respArray = resp.split("-");
document.getElementById('callElapsed').value = respArray[0]; //value set here is 47
document.getElementById('callDuration').value = respArray[1]; // value set here is 240
document.getElementById('mills').value = respArray[1]/100 * 1000 ;
}
}
}
The problem is that you are doing the calculations inside of your callback, so that when you start, all of your variables are still 0.
Pull the time calculation out into its own function, and call that before you call setInterval, and your values will start with the right numbers. (Continue to call it in your callback, of course.)
You also are re-scheduling your setInterval call inside move. This is probably wrong, because it will be re-called every interval, so now you have 2 functions being called on a timer. If you use setTimeout, then you might want to reschedule, but not with setInterval.
You also have the same calculation done twice -- JavaScript is real code, and you should treat it as such; Pull that out into a function you can call.
-- Edit --
Now call calculate() from move() so you don't have the same code in 2 places. ;-)
callDuration and callElapsed are only set from handleDurationElapsedRequest, and only when the request is finished. That's probably why you're getting 0. What exactly are you trying to do here? Is the whole page on line somewhere?
Thanks for help. I have fixed the problem. The problem was I was reading the values 'callDuration' and 'callElapsed' before they were even updated after they have been retrieved from the server. I fixed this by setting a timeout of 1.5 seconds before the code that reads these values is executed ie window.setTimeout("calculate()",1500);
Thanks for the help again.