I'm trying to implement basic 60 sec counter(A p element with idcounter), that is triggered after a button(counter_start()) is pressed.But I want delay of 1 sec between this and make sure this updates in browser window in real-time
<script type="text/javascript">
function counter_start(){
x=0
for(i=0;i<60;i++){
x++;
document.getElementById("counter").innerHTML=x;
}
}
</script>
P.S: There might be other simple methods of implementing a timer.But it's not about timer...actually I'm a student and trying to figure out the architecture and mechanism of this.
EDIT: please post tested versions of the code, as some of em' posted below DO NOT update in real time
Try this Example
Hope it will work for u
JS
for(i = 1; i <= 3; i++)
{
(function(i){
setTimeout(function(){
alert(i);
}, 1000 * i);
}(i));
}
Javascript operates synchronously in the browser.
You need to use setTimeout or setInterval to schedule the for loop's body to be called every second. I'm using setTimeout in the below example for easier "garbage collection"; we will never reschedule the tick to happen after we don't need to update things anymore.
<script type="text/javascript">
var counter = 0;
function counter_tick() {
if(counter < 60) {
counter++;
document.getElementById("counter").innerHTML = counter;
setTimeout(counter_tick, 1000); // Schedule next tick.
}
}
function counter_start() {
counter_tick(); // First update, also schedules next tick to happen.
}
</script>
It sounds like you are looking for a way to pause the current thread, which isn't possible in JavaScript and would probably be a bad idea anyway (the user's browser would lock up while the thread was paused).
A timer is really the way to go with this, otherwise you are fighting the way the language is intended to work.
There is no sleep-function in JS. But you can use window.setTimeout to call a function in given intervals:
function counter_start(){
// get current value
var value = document.getElementById("counter").innerHTML*1;
// leave function if 60 is reached
if(value == 60) {
return;
}
// set the innerHTML to the last value + 1
document.getElementById("counter").innerHTML=value+1;
// call next iteration
window.setTimeout(function(){counter_start()}, 100);
}
counter_start();
JSFiddle-Demo
For-loops run to completion, so you wouldn't usually use one for this.
You just need a timer and a variable to increment:
var maketimer = function(){
var tick = 0,
interval_ms = 1000,
limit = 10,
id;
return {
start: function(){
var timer = this;
console.log('start');
id = setInterval(function(){
if(tick === limit){
timer.stop();
timer.reset();
return;
}
tick += 1;
console.log(tick);
}, interval_ms);
},
stop: function(){
console.log('stop');
clearInterval(id);
},
reset: function(){
console.log('reset');
tick = 0;
}
};
};
var t = maketimer();
t.start();
If you really need to use a for-loop, then you could use a generator function. They're part of the proposed ES6 spec., and you'll need Firefox 26+ to try this out. However the only point of doing this would be to learn about generator functions.
var maketimer = function(){
var interval_ms = 1000,
limit = 10,
id,
loop,
it;
loop = function*(){
var i;
for(i=1; i<=limit; i+=1){
yield i;
}
};
it = loop();
return {
start: function(){
var timer = this;
console.log('start');
id = setInterval(function(){
var tick = it.next();
console.log(tick.value);
if(tick.done){
timer.stop();
timer.reset();
return;
}
}, interval_ms);
},
stop: function(){
console.log('stop');
clearInterval(id);
},
reset: function(){
console.log('reset');
it = loop();
}
};
};
var t = maketimer();
t.start();
Try this::
var x=0;
var myVar;
function myTimer() {
x++;
document.getElementById("counter").innerHTML = x;
if(x==60)
clearInterval(myVar);
}
function counter_start(){
myVar=setInterval(function(){myTimer()},1000);
}
Related
I learn Javascript, just trying to understand how to work with setInterval in different situations.
Now I have problem situation, please someone explain me where is the mistake, and how to do it correctly.
Problem situation:
I want by click to get new coordinate from counter and console log it.
For example I click on a button, and console shows me that:
0
after 2000 ms 1
after 2000 ms 2
after 2000 ms 3
and so on
for example we have a function that do something with coordinates, just console log it's enough:
var showUs = function(coordinate){
console.log(coordinate)
}
another function is a counter that increase it:
var increase = function(){
for(var i = 0; i < 50; i+=1){
showUs(i);
}
}
and the last is the function that should shows coordinate with interval:
somebuttom.onclick = function(){
setInterval(function(){ increase() }, 2000);
}
Just noticed your update. If you want to do it that way then try this:
DEMO
var somebutton = document.getElementById('somebutton');
var showUs = function(coordinate){
console.log(coordinate)
}
var increase = function(){
var i = 0;
var si = setInterval(function(){
if(i < 50){
showUs(i);
i++;
}else{
clearInterval(si);
}
}, 2000);
}
somebutton.onclick = function(){
increase();
}
When i run this code : `
for (var start = 1; start < 10; start++) {
setTimeout(function () {
alert('hello');
}, 3000 * start);
}
alert('Finish');
why the for loop has not finished ,but the code 'alert('Finish')' still run .how to make alert('Finish') run after finishing for loop .Thanks .
Technically that's what its already doing.
The loop runs (setting the timeouts) and then the "finish" alert fires. What I'm guessing you want is the "finish" to fire after all the timeouts have fired off. Easied way to do that would probably be add the finish to its own timeout (so it runs after that amount of time).
Somthing like:
for (var start = 1; start < 10; start++){
setTimeout(function () { console.log('hello'); }
, 10 * start);};
// use final "start" time to set last timeout to fire off its event, after all other timeouts have run
setTimeout(function () {
console.log('Finish');
}, 10 * (start+1));
note: I changed the timings & used console logs so it runs quicker for testing.
You can try this code:
var counter = 1;
for(var i = counter; i < 10; i++){
setTimeout(function(){
counter++;
if(counter == 10){
alert("Finish");
}
else
alert("In process");
}, 10 * i);
}
And see this demo
I would like to propose a different alternative, using setInterval, which imho is better suited for reapeating tasks:
var start = 1;
var interval = setInterval(function(){
console.log('hello ' + start);
if (++start === 10) {
console.log('all done');
clearInterval(interval);
}
}, 3000);
This has the advantage of immediately logging 'all done' after the last iteration.
Well I did not know what exactly would be a good title for this because it is a most peculiar situation or I'm abnormally dumb.
Here's what im trying to do.
Create a simple <meter> tag which is new in HTML5. The main issue is with my javascript. Im trying to increment the value of the meter tag gradually in my javascript. But somehow it doesn't work the way i want.
JavaScript.
for (var i = 0; i <= 10; i++) {
var a = document.getElementById("mtr1");
setTimeout(function () {
console.log(i);
a.value = i;
}, 250);
}
I'm trying to increase the value of the meter gradually every 250 ms.This doesn't happen. Instead the meter jumps straight to 10.
What interested me was the value of i that i got in the console. I got instances of 10, instead of 1,2,3...10.
Why does this happen?
FIDDLE
It's a JavaScript closures' classic. Here i is an actual reference to the variable, not its copy. After you've iterated through the loop it has the value of 10, that's why all log invocations write 10 to log.
This should work better:
for (var i = 0; i <= 10; i++) {
var a = document.getElementById("mtr1");
setTimeout(function (i) {
return function() {
console.log(i);
a.value = i;
};
}(i), 250 * i);
}
Here the most inner i is the setTimeout's callback argument, not the variable which you've declared in the loop body.
You should read more about closures in JavaScript. When a variable gets closed over, it's the same exact variable, not a copy. Since setTimeout is asynchronous, the whole loop finishes before any of the functions run, therefore the i variable will be 10 everywhere.
DEMO
function incMtrAsync(max, delay, el) {
if (el.value++ < max) {
setTimeout(incMtrAsync.bind(null, max, delay, el), delay);
}
}
incMtrAsync(10, 250, document.getElementById("mtr1"));
The above implementation implements the loop using a recursive approach. Everytime inMtrAsync is called, it checks if the value of the meter reached the max value, and if not, registers another timeout with a callback to itself.
If you want to delay the initial increment as well, just wrap the first call in another timeout.
setTimeout(incMtrAsync.bind(null, 10, 250, document.getElementById("mtr1")), 250);
Nobody used setInterval, so here's my solution ( http://jsfiddle.net/Qh6gb/4/) :
var a = document.getElementById("mtr1");
var i = 0;
var interval = setInterval(function () {
console.log(i);
a.value = ++i;
if (i == 10) {
clearInterval(interval);
}
}, 250);
The problem you describe happens before the asyncronous call to setTimeout in your original version sees a value of 10 for i because that is its value at the moment the callback is executed.
So, this is a problem with the scope of the closure, to make it work you should make it like this:
for (var i = 0; i <= 10; i++) {
var a = document.getElementById("mtr1");
(function (i, a) {
setTimeout(function () {
console.log(i);
a.value = i;
}, 250);
})(i, a);
}
also, since a is always the same, this should be better:
var a = document.getElementById("mtr1");
for (var i = 0; i <= 10; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
a.value = i;
}, 250);
})(i);
}
If then you want to see the counter "ticking up", this will make it visible:
var a = document.getElementById("mtr1");
for (var i = 0; i <= 10; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
a.value = i;
}, 1000 * i);
})(i);
}
See http://jsfiddle.net/LDt4d/
It happens because you called setTimeout, which is "asynchronous". So setTimeout is called 10times but after whole loop is done then it is executed. Therefore, i = 10 in each call...
http://jsfiddle.net/Qh6gb/9/
there is the solution:
var i = 1,
meter = document.getElementById("mtr1");
function increase() {
meter.value = i++;
console.log(i);
if(i<=10) {
setTimeout(increase, 250);
}
}
setTimeout(increase, 250);
you can use timeout jquery plugin:. It is easier
However you should calculate your timeout ,
For you ,timeout=250*max=250*10=2500
So
$('meter').timeout(2500);
Demo
Run for loop inside the function instead of declaring a closure in every step of the loop.
JSFIDDLE: http://jsfiddle.net/Qh6gb/3/
var a = document.getElementById("mtr1");
setTimeout(function () {
for (var i = 0; i < 10; i++) {
console.log(i);
a.value = i;
}
}, 250);
I hope I understand right. Please try and tell me if you got solution.
var count = 0;
function increment(){
document.getElementById("meter").value = count;
count++;
if(count ==10)
count=0;
}
setInterval(increment, 250);
Please check with jsFiddle
You're creating multiple functions that are all being set off at the same time.
Multiply the timer by i for correct delay.
for (var i = 0; i <= 10; i++) {
var a = document.getElementById("mtr1");
setTimeout(function () {
console.log(i);
a.value = i;
}, 250 * i);
}
This question already has answers here:
Changing the interval of SetInterval while it's running
(17 answers)
Closed 9 years ago.
Here is an example situation.
var count,
time = 1000;
setInterval(function(){
count += 1;
}, time);
The code above will add 1 to the "count" var, very 1000 milliseconds.
It seems that setInterval, when triggered, will use the time it sees on execution.
If that value is later updated it will not take this into account and will continue to fire with the initial time that was set.
How can I dynamically change the time for this Method?
Use setTimeout instead with a callback and a variable instead of number.
function timeout() {
setTimeout(function () {
count += 1;
console.log(count);
timeout();
}, time);
};
timeout();
Demo here
Shorter version would be:
function periodicall() {
count++;
setTimeout(periodicall, time);
};
periodicall();
Try:
var count,
time = 1000,
intId;
function invoke(){
intId = setInterval(function(){
count += 1;
if(...) // now i need to change my time
{
time = 2000; //some new value
intId = window.clearInterval(intId);
invoke();
}
}, time);
}
invoke();
You cannot change the interval dynamically because it is set once and then you dont rerun the setInterval code again. So what you can do it to clear the interval and again set it to run. You can also use setTimeout with similar logic, but using setTimeout you need to register a timeout everytime and you don't need to possibly use clearTimeout unless you want to abort in between. If you are changing time everytime then setTimeout makes more sense.
var count,
time = 1000;
function invoke() {
count += 1;
time += 1000; //some new value
console.log('displ');
window.setTimeout(invoke, time);
}
window.setTimeout(invoke, time);
You cant (as far as i know) change the interval dynamically. I would suggesst to do this with callbacks:
var _time = 1000,
_out,
_count = 0,
yourfunc = function() {
count++;
if (count > 10) {
// stop
clearTimeout(_out); // optional
}
else {
// your code
_time = 1000 + count; // for instance
_out = setTimeout(function() {
yourfunc();
}, _time);
}
};
integers are not passed by reference in JavaScript meaning there is no way to change the interval by changing your variable.
Simply cancel the setInterval and restart it again with the new time.
Example can be found here:
http://jsfiddle.net/Elak/yUxmw/2/
var Interval;
(function () {
var createInterval = function (callback, time) {
return setInterval(callback, time);
}
Interval = function (callback, time) {
this.callback = callback;
this.interval = createInterval(callback, time);
};
Interval.prototype.updateTimer = function (time) {
clearInterval(this.interval);
createInterval(this.callback, time);
};
})();
$(document).ready(function () {
var inter = new Interval(function () {
$("#out").append("<li>" + new Date().toString() + "</li>");
}, 1000);
setTimeout(function () {
inter.updateTimer(500);
}, 2000);
});
I have a ajax javascript method that pulls data from a page etc.
I want this process to run on a timed interval, say every minute.
But I don't want it to loop forever, so max out at 3 times.
What is the best way to implement this?
Like this:
var runCount = 0;
function timerMethod() {
runCount++;
if(runCount > 3) clearInterval(timerId);
//...
}
var timerId = setInterval(timerMethod, 60000); //60,000 milliseconds
A closure-based solution, using setInterval() and clearInterval():
// define a generic repeater
var repeater = function(func, times, interval) {
var ID = window.setInterval( function(times) {
return function() {
if (--times <= 0) window.clearInterval(ID);
func();
}
}(times), interval);
};
// call the repeater with a function as the argument
repeater(function() {
alert("stuff happens!");
}, 3, 60000);
EDIT: Another way of expressing the same, using setTimeout() instead:
var repeater = function(func, times, interval) {
window.setTimeout( function(times) {
return function() {
if (--times > 0) window.setTimeout(arguments.callee, interval);
func();
}
}(times), interval);
};
repeater(function() {
alert("stuff happens!");
}, 3, 2000);
Maybe the latter is a bit easier to understand.
In the setTimeout() version you can ensure that the next iteration happens only after the previous one has finished running. You'd simply move the func() line above the setTimeout() line.
A reusable approach
function setMaxExeuctionInterval( callback, delay, maxExecutions )
{
var intervalCallback = function()
{
var self = intervalCallback;
if ( 'undefined' == typeof self.executedIntervals )
{
self.executedIntervals = 1;
}
if ( self.executedIntervals == maxExecutions )
{
clearInterval( self.interval )
}
self.executedIntervals += 1;
callback();
};
intervalCallback.interval = setInterval( intervalCallback, delay );
}
// console.log requires Firebug
setMaxExeuctionInterval( function(){ console.log( 'hi' );}, 700, 3 );
setMaxExeuctionInterval( function(){ console.log( 'bye' );}, 200, 8 );
This anonymous function (it doesn't introduce any new globals) will do what you need. All you have to do is replace yourFunction with your function.
(function(fn, interval, maxIterations) {
var iterations = 0,
id = setInterval(function() {
if (++iterations > maxIterations)
return clearInterval(id);
fn();
}, interval);
})(yourFunction, 60000, 3);
you can do with setInterval
var count = 0;
var interval = setInterval(yourFunction(), 1000);
function yourFunction (){
clearInterval(interval);
if(count < 3){
count ++;
interval = setInterval(yourFunction(), 1000);
}
// your code
}
To extend Tomalak function:
If you want to know how many cycles are left:
var repeater = function(func, times, interval) {
window.setTimeout( function(times) {
return function() {
if (--times > 0) window.setTimeout(arguments.callee, interval);
func(times);
}
}(times), interval);
}
and use:
repeater(function(left){
//... (do you stuff here) ...
if(left == 0) {
alert("I'm done");
}
}, 3, 60000);
Use setInterval, be sure to get a reference.
var X=setInterval(....);
Also, have a global counter
var c=0;
Inside the function called by the setIntervale do:
c++;
if(c>3) window.clearInterval(X);
You can use setInterval() and then inside the called function keep a count of how many times you've run the function and then clearInterval().
Or you can use setTimeout() and then inside the called function call setTimeout() again until you've done it 3 times.
var testTimeInt = 3;
function testTime(){
testTimeInt--;
if(testTimeInt>0)
setTimeOut("testTime()", 1000);
}
setTimeOut("testTime()", 1000);