Javascript setInterval() - Why does my "input" parameter changes to undefined? - javascript

I've been working on the below code but couldn't figure out that why does my function parameter "input" changes to undefined after 1 second?
Here is the code:
<div id="new_time"></div>
<div id='input'></div>
<script>
var mins = 0;
var hrs = 0;
var secs = 0;
var test = 0;
function time_calc(input)
{
document.getElementById('new_time').innerHTML = secs++;
document.getElementById('input').innerHTML = input;
if (secs>59)
{
mins += 1;
secs = 0;
if (mins>59)
{
hrs += 1;
mins = 0;
}
}
while (secs == input)
{
clearInterval(secs_inc);
}
document.getElementById('new_time').innerHTML = hrs + ":" + mins + ":" + secs;
}
time_calc(20);
var secs_inc = setInterval(time_calc, 1000);
</script>

What do you expect it to be? You call the function time_calc after one second using setInterval. But it is called just like that, without arguments. So the argument input doesn't get a value, making it undefined.
When you try to assign it to the element, it is translated to the text undefined.
One way to solve this, is wrapping it in a function. This can be an anonymous function:
var secs_inc = setInterval(function(){timecalc(20)}, 1000);
Dressed down example:
function time_calc(input) {
document.getElementById('input').innerText = input;
}
setInterval(function(){time_calc(20)}, 3000);
<span id="input">Wait for it....</span>
If you call setInterval(time_calc(20), 1000), you actually call the function time_calc(), and pass the result to setInterval.
But you must not call it. You need to pass the function itself to setInterval, so setInterval can call it later. That's why in your original snippet you passed time_calc without parentheses. It's just the function without the call.
What I did, is wrap the call to time_calc(20) in another (anonymous) function that also doesn't have arguments. And now it's the anonymous wrapper function that is called by setInterval, which in turn calls time_calc with an argument.
It doesn't have to be an anonymous function by the way. I think for this case it's the easiest solution, but declaring an actual named function as #sudhAnsu63 demonstrated in his answer should work too.

Try calling your function like this.
var secs_inc = setInterval(new function(){
time_calc(20);}, 1000);
Or
function Calltime()
{
time_calc(20);
}
var secs_inc = setInterval(Calltime, 1000);

Related

javascript function does not work with passing a parameter [duplicate]

Please advise how to pass parameters into a function called using setInterval.
My example setInterval(funca(10,3), 500); is incorrect.
You need to create an anonymous function so the actual function isn't executed right away.
setInterval( function() { funca(10,3); }, 500 );
Add them as parameters to setInterval:
setInterval(funca, 500, 10, 3);
The syntax in your question uses eval, which is not recommended practice.
now with ES5, bind method Function prototype :
setInterval(funca.bind(null,10,3),500);
Reference here
setInterval(function(a,b,c){
console.log(a + b +c);
}, 500, 1,2,3);
//note the console will print 6
//here we are passing 1,2,3 for a,b,c arguments
// tested in node v 8.11 and chrome 69
You can pass the parameter(s) as a property of the function object, not as a parameter:
var f = this.someFunction; //use 'this' if called from class
f.parameter1 = obj;
f.parameter2 = this;
f.parameter3 = whatever;
setInterval(f, 1000);
Then in your function someFunction, you will have access to the parameters. This is particularly useful inside classes where the scope goes to the global space automatically and you lose references to the class that called setInterval to begin with. With this approach, "parameter2" in "someFunction", in the example above, will have the right scope.
setInterval(function,milliseconds,param1,param2,...)
Update: 2018 - use the "spread" operator
function repeater(param1, param2, param3){
alert(param1);
alert(param2);
alert(param3);
}
let input = [1,2,3];
setInterval(repeater,3000,...input);
You can use an anonymous function;
setInterval(function() { funca(10,3); },500);
By far the most practical answer is the one given by tvanfosson, all i can do is give you an updated version with ES6:
setInterval( ()=>{ funca(10,3); }, 500);
Quoting the arguments should be enough:
OK --> reloadIntervalID = window.setInterval( "reloadSeries('"+param2Pass+"')" , 5000)
KO --> reloadIntervalID = window.setInterval( "reloadSeries( "+param2Pass+" )" , 5000)
Note the single quote ' for each argument.
Tested with IE8, Chrome and FireFox
const designated = "1 jan 2021"
function countdown(designated_time){
const currentTime = new Date();
const future_time = new Date(designated_time);
console.log(future_time - currentTime);
}
countdown(designated);
setInterval(countdown, 1000, designated);
There are so many ways you can do this, me personally things this is clean and sweet.
The best solution to this answer is the next block of code:
setInterval(() => yourFunction(param1, param2), 1000);
I know this topic is so old but here is my solution about passing parameters in setInterval function.
Html:
var fiveMinutes = 60 * 2;
var display = document.querySelector('#timer');
startTimer(fiveMinutes, display);
JavaScript:
function startTimer(duration, display) {
var timer = duration,
minutes, seconds;
setInterval(function () {
minutes = parseInt(timer / 60, 10);
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
--timer; // put boolean value for minus values.
}, 1000);
}
This worked for me
let theNumber = document.getElementById('number');
let counter = 0;
function skills (counterInput, timer, element) {
setInterval(() => {
if(counterInput > counter) {
counter += 1;
element.textContent = `${counter} %`
}else {
clearInterval();
}
}, timer)
}
skills(70, 200, theNumber);
This works setInterval("foo(bar)",int,lang);.... Jon Kleiser lead me to the answer.
Another solution consists in pass your function like that (if you've got dynamics vars) :
setInterval('funca('+x+','+y+')',500);
You can use a library called underscore js. It gives a nice wrapper on the bind method and is a much cleaner syntax as well. Letting you execute the function in the specified scope.
http://underscorejs.org/#bind
_.bind(function, scope, *arguments)
That problem would be a nice demonstration for use of closures. The idea is that a function uses a variable of outer scope. Here is an example...
setInterval(makeClosure("Snowden"), 1000)
function makeClosure(name) {
var ret
ret = function(){
console.log("Hello, " + name);
}
return ret;
}
Function "makeClosure" returns another function, which has access to outer scope variable "name". So, basically, you need pass in whatever variables to "makeClosure" function and use them in function assigned to "ret" variable. Affectingly, setInterval will execute function assigned to "ret".
I have had the same problem with Vue app. In my case this solution is only works if anonymous function has declared as arrow function, regarding declaration at mounted () life circle hook.
Also, with IE Support > 9, you can pass more variables insider set interval that will be taken by you function. E.g:
function myFunc(arg1, arg2){};
setInterval(myFunc, 500, arg1, arg2);
Greetings!

How to exec a function after previous ends?

guys. It's a timer. I wanna run the timer and when it's end do something else(like a warning),and then run again with other amount of minutes. But I can't cause always only the second call is executed:
$(document).ready(function() {
timer(5,timer(25));
// timer(5);
// timer(25); do not work... only exec de last one
});
function timer(countTo,callback){
var time = 10; /* how long the timer runs for */
var initialOffset = '440';
var i = 1
var interval = setInterval(function() {
$('.circle_animation').css('stroke-dashoffset', initialOffset-(i*(initialOffset/countTo)));
$('h2').text(i);
if (i == countTo) {
clearInterval(interval);
}
i++;
}, 1000);
callback();
}
Which is the best solution? There is something that I am not understanding... Thanks anyway!
Well, first off:
timer(5,timer(25));
If you think this line will execute timer(5), and then at the end of timer(5) it will execute timer(25), you are mistaken. This is actually going to evaluate timer(25) immediately, and pass its return value (undefined) as the second parameter to timer(5,undefined).
If you intended to pass that as a callback, you need to pass a function. So you could do:
timer(5,timer.bind(null,25));
But, for that matter, you don't even check if callback exists before attempting to invoke it, so you probably are getting a reference error anyway.
timer(5,timer(25));
starts two timers and passes the result of the second (undefined) to the first as callback. You want:
timer(5,timer.bind(window,25));
And the callback needs to be executed if i==countTo ...
Is this what you want?
timer(5,function(){timer(25)});
Your problem is here:
timer(5,timer(25));
You should type
timer(5, function(){
timer(25)
});
//or using ES6 syntax
timer(5, () => timer(25));
because timer(25) returns its value (this function doesn't return value so it tries to invoke undefined), not that function.
Also read about closures, it might be helpful.
Instead of runing a callback(), you need to run the function itself (timer()). You'll also need to run a for loop inside your function that checks how many times the function has already run. If it reaches your desired maximum, break out of that. This way it won't run indefinitely.
In the following example, the timer() function executes five times, which is what I'm assuming you want by calling timer(5).
$(document).ready(function() {
timer(5);
});
function timer(countTo) {
for (var iterations = 0; iterations < countTo; iterations++) {
var time = 10; /* how long the timer runs for */
var initialOffset = '440';
var i = 1
var interval = setInterval(function() {
$('.circle_animation').css('stroke-dashoffset', initialOffset - (i * (initialOffset / countTo)));
$('h2').text(i);
if (i == countTo) {
clearInterval(interval);
}
}, 1000);
timer();
console.log("Iteration:", iterations + 1);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
To run the function 25 times after this, all you have to do is call timer(25) directly after timer(5):
$(document).ready(function() {
timer(5);
timer(25);
});
$(document).ready(function() {
timer(5);
timer(25);
});
function timer(countTo) {
for (var iterations = 0; iterations < countTo; iterations++) {
var time = 10; /* how long the timer runs for */
var initialOffset = '440';
var i = 1
var interval = setInterval(function() {
$('.circle_animation').css('stroke-dashoffset', initialOffset - (i * (initialOffset / countTo)));
$('h2').text(i);
if (i == countTo) {
clearInterval(interval);
}
}, 1000);
timer();
console.log("Iteration:", iterations + 1);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope this helps! :)

Calling the setTimeout Function recursively and passing an anonymous function

I am confused on the difference between this syntax:
var timerId;
function clockStart(){
// debugger;
if(timerId){
return;
}
update();
// THIS LINE BELOW *********************************************
var timerId = setTimeout(function(){clockStart()}, 1000);
}
function clockStop(){
timerId = null;
}
function update(){
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
if(hours < 10) {
hours = '0'+hours;
}
document.getElementById('hour').innerHTML = hours;
if(minutes < 10){
minutes = 0+minutes;
}
document.getElementById('min').innerHTML = minutes;
if(seconds < 10){
seconds = '0' + seconds;
}
document.getElementById('sec').innerHTML = seconds;
}
I provided both functions being called but the main part of this function I do not understand is why I need to pass an anonymous function to call my clockStart() function.
My function works when I use this syntax:
var timerId = setTimeout(function(){clockStart()}, 1000);
But it doesn't work when I use:
var timerId = setTimeout(clockStart(), 1000);
I have been working a while on these two functions and I honestly stumbled upon this by accident. I really don't see what the anonymous function is doing besides invoking my clockStart function. But in my opinion, my clockStart() function should be invoked every second(1000ms) since it is calling itself, so why does it need an anonymous function to invoke it? Shouldn't it be invoking itself?
If you would like to see this digital 'clock's' full code please checkout my codepen link.
This line:
var timerId = setTimeout(clockStart(), 1000);
is calling clockStart() immediately and passing the return result from that function to setTimeout(). Since the function doesn't return anything, you're effectively doing this:
clockStart();
var timerId = setTimeout(undefined, 1000);
which obviously doesn't do what you want.
You can use this instead:
var timerId = setTimeout(clockStart, 1000);
In this case, you want to pass a function reference to setTimeout() which means you do not include the parens. When you include the parens, that means to execute it NOW. When you just pass the name of the function, that is just a reference to the function (think of it like a handle) by which setTimeout() can call it later. That's what you want.
When you do this:
var timerId = setTimeout(function(){clockStart()}, 1000)
you're just defining an anonymous function and passing a reference to that anonymous function to to setTimeout() which works fine, but is not necessary in this case since you can just pass the clockStart name as in my third code example above.
Since you asked about how a function can call something later, I'll show you a simple example. Here's a function that takes a starting value, an ending value, an increment and a callback function. This will call the callback and pass it the value that it's incrementing until the value exceeds the end value.
// define an increment function that will call a callback
// multiple times based on the start, end and increment arguments
function eachIncrement(start, end, increment, callback) {
// the function argument named callback contains
// a function reference
var val = start;
while (val <= end) {
// execute the function reference and
// pass it the current val
callback(val);
val += increment;
}
}
// define a function that we want to be called later
function processValues(num) {
// this will get called multiple times with
// values 1, 4, 7, 10
}
// set up the increment parameters and pass a function reference
eachIncrement(1, 10, 3, processValues);

setInterval() not repeating. Works only 1 time

I'm trying to have a div's left property change by its self - one every second when your hovering over so I made this:
$("div.scroll_left").hover(function(){
var left_num = $('div.license_video').css("left")
var left_num1 = parseInt(left_num, 10) - 1;
var timerID = setInterval(alert(left_num1), 1000);
//var timerID = setInterval(slideleft(left_num1), 1000);
},function(){
clearInterval(timerID);
});
//function slideleft(left_num){
//$('.license_video').css('left', left_num + "%");
//}
In theory you would think it repeat till you move your cursor off which clears the interval. When I hover over it does it one time and never repeats (there are no errors). Then when I hover off it gives a error "Uncaught ReferenceError: timerID is not defined"
setInterval isn't working at all. You aren't passing it a function as the first argument.
You are calling alert immediately and trying to use it's return value as the function to repeat.
var timerID = setInterval(function () { alert(left_num1) }, 1000);
So you've got two different problems here:
// (1) timerID needs to be defined in a scope accessible to both hover callbacks
var timerID = null;
$("div.scroll_left").hover(function(){
var left_num = $('div.license_video').css("left")
var left_num1 = parseInt(left_num, 10) - 1;
// (2) Pass a *function* to setInterval
timerID = setInterval(function () {
alert(left_num1)
}, 1000);
}, function(){
clearInterval(timerID);
timerID = null;
});
When you write
setInterval(alert(left_num1), 1000);
// or
setInterval(slideleft(left_num1), 1000);
you are passing the value returned by calling alert() or slideleft() (respectively) to setInterval. You are not passing the function itself.
You are assigning null to be the function to call. Why? Because you called alert and assigned its return value to the setInterval parameter.
Instead, use an anonymous function:
setInterval(function() {doStuff();},1000);
Very easy ;-) ... i love jquery, no matter a version... u need javascript pure is send pm me is can help.
umavez = 0;
setInterval(function() {
if (umavez == 0) {
for (x=0;x<10;x++) {
$('div.test').append('<div>'+x+'</div>');
}
}
umavez = 1;
}, 500);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="test">Linha:</div>

having trouble using setInterval and with random number generation

I'm trying to create a random quote generator. I have created a function called timer that runs another function pickQuote every 400ms but at the moment this doesn't seem to work. in pickQuote I run a function randomNumberGen that creates a random number. My problem in the randomNumberGen is that I want to have an if or if..else in place that checks whether or not the new random number is different from the current quotes[randomNumber] but i'm unsure how to do this.
Can anyone provide me with some insight on how I can achieve this?
My current effort can be viewed here: http://jsbin.com/aqinud/12/edit
index is not defined outside $.each. Variables in functions are not accessible outside it if you use var.
What I recommend is altering the function as follows:
function randomNumberGen() {
//generate randomNumber based on length of array
// round it down (parseInt is for string->number conversion)
var thisRandomNumber = Math.floor(Math.random() * len);
if ( randomNumber === thisRandomNumber ) {
randomNumberGen();
} else {
randomNumber = thisRandomNumber;
}
}
So, first create a random number and only if it's different from randomNumber, update it with the newly created one. Otherwise, try again.
Also, setTimeout requires a function, so don't invoke it yet:
runQuotePicker = setInterval(pickQuote, 400);
http://jsbin.com/aqinud/13/edit
Perhaps something like this:
var currentNumber = -1;
function randomNumberGen() {
var num = parseInt(Math.random() * (len) );
if(currentNumber != num){
currentNumber = num;
return num;
} else {
return randomNumberGen();
}
}
I noticed you had incorrectly passed 'pickQuote' to setInterval. Try wrapping the callback in an anonymous function:
function timer() {
runQuotePicker = setInterval(function(){
pickQuote();
}, 1000);
}
Otherwise you're scheduling the result of pickQuote to be invoked ever x milliseconds.

Categories

Resources