javascript function does not work with passing a parameter [duplicate] - javascript
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!
Related
How to resolve a promise with a parameter in setTimeout [duplicate]
I have some JavaScript code that looks like: function statechangedPostQuestion() { //alert("statechangedPostQuestion"); if (xmlhttp.readyState==4) { var topicId = xmlhttp.responseText; setTimeout("postinsql(topicId)",4000); } } function postinsql(topicId) { //alert(topicId); } I get an error that topicId is not defined Everything was working before I used the setTimeout() function. I want my postinsql(topicId) function to be called after some time. What should I do?
setTimeout(function() { postinsql(topicId); }, 4000) You need to feed an anonymous function as a parameter instead of a string, the latter method shouldn't even work per the ECMAScript specification but browsers are just lenient. This is the proper solution, don't ever rely on passing a string as a 'function' when using setTimeout() or setInterval(), it's slower because it has to be evaluated and it just isn't right. UPDATE: As Hobblin said in his comments to the question, now you can pass arguments to the function inside setTimeout using Function.prototype.bind(). Example: setTimeout(postinsql.bind(null, topicId), 4000);
In modern browsers (ie IE11 and beyond), the "setTimeout" receives a third parameter that is sent as parameter to the internal function at the end of the timer. Example: var hello = "Hello World"; setTimeout(alert, 1000, hello); More details: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout http://arguments.callee.info/2008/11/10/passing-arguments-to-settimeout-and-setinterval/
After doing some research and testing, the only correct implementation is: setTimeout(yourFunctionReference, 4000, param1, param2, paramN); setTimeout will pass all extra parameters to your function so they can be processed there. The anonymous function can work for very basic stuff, but within instance of a object where you have to use "this", there is no way to make it work. Any anonymous function will change "this" to point to window, so you will lose your object reference.
This is a very old question with an already "correct" answer but I thought I'd mention another approach that nobody has mentioned here. This is copied and pasted from the excellent underscore library: _.delay = function(func, wait) { var args = slice.call(arguments, 2); return setTimeout(function(){ return func.apply(null, args); }, wait); }; You can pass as many arguments as you'd like to the function called by setTimeout and as an added bonus (well, usually a bonus) the value of the arguments passed to your function are frozen when you call setTimeout, so if they change value at some point between when setTimeout() is called and when it times out, well... that's not so hideously frustrating anymore :) Here's a fiddle where you can see what I mean.
I recently came across the unique situation of needing to use a setTimeout in a loop. Understanding this can help you understand how to pass parameters to setTimeout. Method 1 Use forEach and Object.keys, as per Sukima's suggestion: var testObject = { prop1: 'test1', prop2: 'test2', prop3: 'test3' }; Object.keys(testObject).forEach(function(propertyName, i) { setTimeout(function() { console.log(testObject[propertyName]); }, i * 1000); }); I recommend this method. Method 2 Use bind: var i = 0; for (var propertyName in testObject) { setTimeout(function(propertyName) { console.log(testObject[propertyName]); }.bind(this, propertyName), i++ * 1000); } JSFiddle: http://jsfiddle.net/MsBkW/ Method 3 Or if you can't use forEach or bind, use an IIFE: var i = 0; for (var propertyName in testObject) { setTimeout((function(propertyName) { return function() { console.log(testObject[propertyName]); }; })(propertyName), i++ * 1000); } Method 4 But if you don't care about IE < 10, then you could use Fabio's suggestion: var i = 0; for (var propertyName in testObject) { setTimeout(function(propertyName) { console.log(testObject[propertyName]); }, i++ * 1000, propertyName); } Method 5 (ES6) Use a block scoped variable: let i = 0; for (let propertyName in testObject) { setTimeout(() => console.log(testObject[propertyName]), i++ * 1000); } Though I would still recommend using Object.keys with forEach in ES6.
Hobblin already commented this on the question, but it should be an answer really! Using Function.prototype.bind() is the cleanest and most flexible way to do this (with the added bonus of being able to set the this context): setTimeout(postinsql.bind(null, topicId), 4000); For more information see these MDN links: https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function/bind#With_setTimeout
You can pass the parameter to the setTimeout callback function as: setTimeout(function, milliseconds, param1, param2, ...) eg. function myFunction() { setTimeout(alertMsg, 3000, "Hello"); } function alertMsg(message) { alert(message) }
Some answers are correct but convoluted. I am answering this again, 4 years later, because I still run into overly complex code to solve exactly this question. There IS an elegant solution. First of all, do not pass in a string as the first parameter when calling setTimeout because it effectively invokes a call to the slow "eval" function. So how do we pass in a parameter to a timeout function? By using closure: settopic=function(topicid){ setTimeout(function(){ //thanks to closure, topicid is visible here postinsql(topicid); },4000); } ... if (xhr.readyState==4){ settopic(xhr.responseText); } Some have suggested using anonymous function when calling the timeout function: if (xhr.readyState==4){ setTimeout(function(){ settopic(xhr.responseText); },4000); } The syntax works out. But by the time settopic is called, i.e. 4 seconds later, the XHR object may not be the same. Therefore it's important to pre-bind the variables.
I know its been 10 yrs since this question was asked, but still, if you have scrolled till here, i assume you're still facing some issue. The solution by Meder Omuraliev is the simplest one and may help most of us but for those who don't want to have any binding, here it is: Use Param for setTimeout setTimeout(function(p){ //p == param1 },3000,param1); Use Immediately Invoked Function Expression(IIFE) let param1 = 'demon'; setTimeout(function(p){ // p == 'demon' },2000,(function(){ return param1; })() ); Solution to the question function statechangedPostQuestion() { //alert("statechangedPostQuestion"); if (xmlhttp.readyState==4) { setTimeout(postinsql,4000,(function(){ return xmlhttp.responseText; })()); } } function postinsql(topicId) { //alert(topicId); }
Replace setTimeout("postinsql(topicId)", 4000); with setTimeout("postinsql(" + topicId + ")", 4000); or better still, replace the string expression with an anonymous function setTimeout(function () { postinsql(topicId); }, 4000); EDIT: Brownstone's comment is incorrect, this will work as intended, as demonstrated by running this in the Firebug console (function() { function postinsql(id) { console.log(id); } var topicId = 3 window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds })(); Note that I'm in agreeance with others that you should avoid passing a string to setTimeout as this will call eval() on the string and instead pass a function.
My answer: setTimeout((function(topicId) { return function() { postinsql(topicId); }; })(topicId), 4000); Explanation: The anonymous function created returns another anonymous function. This function has access to the originally passed topicId, so it will not make an error. The first anonymous function is immediately called, passing in topicId, so the registered function with a delay has access to topicId at the time of calling, through closures. OR This basically converts to: setTimeout(function() { postinsql(topicId); // topicId inside higher scope (passed to returning function) }, 4000); EDIT: I saw the same answer, so look at his. But I didn't steal his answer! I just forgot to look. Read the explanation and see if it helps to understand the code.
The easiest cross browser solution for supporting parameters in setTimeout: setTimeout(function() { postinsql(topicId); }, 4000) If you don't mind not supporting IE 9 and lower: setTimeout(postinsql, 4000, topicId); https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
I know it's old but I wanted to add my (preferred) flavour to this. I think a pretty readable way to achieve this is to pass the topicId to a function, which in turn uses the argument to reference the topic ID internally. This value won't change even if topicId in the outside will be changed shortly after. var topicId = xmlhttp.responseText; var fDelayed = function(tid) { return function() { postinsql(tid); }; } setTimeout(fDelayed(topicId),4000); or short: var topicId = xmlhttp.responseText; setTimeout(function(tid) { return function() { postinsql(tid); }; }(topicId), 4000);
The answer by David Meister seems to take care of parameters that may change immediately after the call to setTimeout() but before the anonymous function is called. But it's too cumbersome and not very obvious. I discovered an elegant way of doing pretty much the same thing using IIFE (immediately inviked function expression). In the example below, the currentList variable is passed to the IIFE, which saves it in its closure, until the delayed function is invoked. Even if the variable currentList changes immediately after the code shown, the setInterval() will do the right thing. Without this IIFE technique, the setTimeout() function will definitely get called for each h2 element in the DOM, but all those calls will see only the text value of the last h2 element. <script> // Wait for the document to load. $(document).ready(function() { $("h2").each(function (index) { currentList = $(this).text(); (function (param1, param2) { setTimeout(function() { $("span").text(param1 + ' : ' + param2 ); }, param1 * 1000); })(index, currentList); }); </script>
In general, if you need to pass a function as a callback with specific parameters, you can use higher order functions. This is pretty elegant with ES6: const someFunction = (params) => () => { //do whatever }; setTimeout(someFunction(params), 1000); Or if someFunction is first order: setTimeout(() => someFunction(params), 1000);
Note that the reason topicId was "not defined" per the error message is that it existed as a local variable when the setTimeout was executed, but not when the delayed call to postinsql happened. Variable lifetime is especially important to pay attention to, especially when trying something like passing "this" as an object reference. I heard that you can pass topicId as a third parameter to the setTimeout function. Not much detail is given but I got enough information to get it to work, and it's successful in Safari. I don't know what they mean about the "millisecond error" though. Check it out here: http://www.howtocreate.co.uk/tutorials/javascript/timers
How i resolved this stage ? just like that : setTimeout((function(_deepFunction ,_deepData){ var _deepResultFunction = function _deepResultFunction(){ _deepFunction(_deepData); }; return _deepResultFunction; })(fromOuterFunction, fromOuterData ) , 1000 ); setTimeout wait a reference to a function, so i created it in a closure, which interprete my data and return a function with a good instance of my data ! Maybe you can improve this part : _deepFunction(_deepData); // change to something like : _deepFunction.apply(contextFromParams , args); I tested it on chrome, firefox and IE and it execute well, i don't know about performance but i needed it to be working. a sample test : myDelay_function = function(fn , params , ctxt , _time){ setTimeout((function(_deepFunction ,_deepData, _deepCtxt){ var _deepResultFunction = function _deepResultFunction(){ //_deepFunction(_deepData); _deepFunction.call( _deepCtxt , _deepData); }; return _deepResultFunction; })(fn , params , ctxt) , _time) }; // the function to be used : myFunc = function(param){ console.log(param + this.name) } // note that we call this.name // a context object : myObjet = { id : "myId" , name : "myName" } // setting a parmeter myParamter = "I am the outer parameter : "; //and now let's make the call : myDelay_function(myFunc , myParamter , myObjet , 1000) // this will produce this result on the console line : // I am the outer parameter : myName Maybe you can change the signature to make it more complient : myNass_setTimeOut = function (fn , _time , params , ctxt ){ return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){ var _deepResultFunction = function _deepResultFunction(){ //_deepFunction(_deepData); _deepFunction.apply( _deepCtxt , _deepData); }; return _deepResultFunction; })(fn , params , ctxt) , _time) }; // and try again : for(var i=0; i<10; i++){ myNass_setTimeOut(console.log ,1000 , [i] , console) } And finaly to answer the original question : myNass_setTimeOut( postinsql, 4000, topicId ); Hope it can help ! ps : sorry but english it's not my mother tongue !
this works in all browsers (IE is an oddball) setTimeout( (function(x) { return function() { postinsql(x); }; })(topicId) , 4000);
if you want to pass variable as param lets try this if requirement is function and var as parmas then try this setTimeout((param1,param2) => { alert(param1 + param2); postinsql(topicId); },2000,'msg1', 'msg2') if requirement is only variables as a params then try this setTimeout((param1,param2) => { alert(param1 + param2) },2000,'msg1', 'msg2') You can try this with ES5 and ES6
setTimeout is part of the DOM defined by WHAT WG. https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html The method you want is:— handle = self.setTimeout( handler [, timeout [, arguments... ] ] ) Schedules a timeout to run handler after timeout milliseconds. Any arguments are passed straight through to the handler. setTimeout(postinsql, 4000, topicId); Apparently, extra arguments are supported in IE10. Alternatively, you can use setTimeout(postinsql.bind(null, topicId), 4000);, however passing extra arguments is simpler, and that's preferable. Historical factoid: In days of VBScript, in JScript, setTimeout's third parameter was the language, as a string, defaulting to "JScript" but with the option to use "VBScript". https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)
You can try default functionality of 'apply()' something like this, you can pass more number of arguments as your requirement in the array function postinsql(topicId) { //alert(topicId); } setTimeout( postinsql.apply(window,["mytopic"]) ,500);
//Some function, with some arguments, that need to run with arguments var a = function a(b, c, d, e){console.log(b, c, d, e);} //Another function, where setTimeout using for function "a", this have the same arguments var f = function f(b, c, d, e){ setTimeout(a.apply(this, arguments), 100);} f(1,2,3,4); //run //Another function, where setTimeout using for function "a", but some another arguments using, in different order var g = function g(b, c, d, e){ setTimeout(function(d, c, b){a.apply(this, arguments);}, 100, d, c, b);} g(1,2,3,4);
#Jiri Vetyska thanks for the post, but there is something wrong in your example. I needed to pass the target which is hovered out (this) to a timed out function and I tried your approach. Tested in IE9 - does not work. I also made some research and it appears that as pointed here the third parameter is the script language being used. No mention about additional parameters. So, I followed #meder's answer and solved my issue with this code: $('.targetItemClass').hover(ItemHoverIn, ItemHoverOut); function ItemHoverIn() { //some code here } function ItemHoverOut() { var THIS = this; setTimeout( function () { ItemHoverOut_timeout(THIS); }, 100 ); } function ItemHoverOut_timeout(target) { //do something with target which is hovered out } Hope, this is usefull for someone else.
As there is a problem with the third optonal parameter in IE and using closures prevents us from changing the variables (in a loop for example) and still achieving the desired result, I suggest the following solution. We can try using recursion like this: var i = 0; var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"]; if(hellos.length > 0) timeout(); function timeout() { document.write('<p>' + hellos[i] + '<p>'); i++; if (i < hellos.length) setTimeout(timeout, 500); } We need to make sure that nothing else changes these variables and that we write a proper recursion condition to avoid infinite recursion.
// These are three very simple and concise answers: function fun() { console.log(this.prop1, this.prop2, this.prop3); } let obj = { prop1: 'one', prop2: 'two', prop3: 'three' }; let bound = fun.bind(obj); setTimeout(bound, 3000); // or function funOut(par1, par2, par3) { return function() { console.log(par1, par2, par3); } }; setTimeout(funOut('one', 'two', 'three'), 5000); // or let funny = function(a, b, c) { console.log(a, b, c); }; setTimeout(funny, 2000, 'hello', 'worldly', 'people');
// These are three very simple and concise answers: function fun() { console.log(this.prop1, this.prop2, this.prop3); } let obj = { prop1: 'one', prop2: 'two', prop3: 'three' }; let bound = fun.bind(obj); setTimeout(bound, 3000); // or function funOut(par1, par2, par3) { return function() { console.log(par1, par2, par3); } }; setTimeout(funOut('one', 'two', 'three'), 5000); // or let funny = function(a, b, c) { console.log(a, b, c); }; setTimeout(funny, 2000, 'hello', 'worldly', 'people');
I think you want: setTimeout("postinsql(" + topicId + ")", 4000);
You have to remove quotes from your setTimeOut function call like this: setTimeout(postinsql(topicId),4000);
Answering the question but by a simple addition function with 2 arguments. var x = 3, y = 4; setTimeout(function(arg1, arg2) { return () => delayedSum(arg1, arg2); }(x, y), 1000); function delayedSum(param1, param2) { alert(param1 + param2); // 7 }
I somehow can't stop my setTimeout() loop
So i have a major function which triggers another function every 2 - 17 seconds but when I try to stop it with clearTimeout() it just goes on and completely ignores the clearTimeout(). So this is my major function: var itemTimer; var stopTimeout; function major (){ var itemTime = Math.floor(Math.random() * 15000) + 2000; itemTimer = setTimeout('items()', itemTime); stopTimeout = setTimeout('major()',itemTime); } And this is my stop timeout function: function stopTimer() { clearTimeout(itemTimer); clearTimeout(stopTimeout); } Thank you for helping
Your setTimeout() is being called incorrectly; you're invoking items() and major(). Instead, you need to pass them as functions to be invoked. Don't pass the brackets to the parameters, and don't wrap the parameters in quote marks. Instead of: itemTimer = setTimeout('items()', itemTime); stopTimeout = setTimeout('major()',itemTime); You're looking for: itemTimer = setTimeout(items, itemTime); stopTimeout = setTimeout(major, itemTime); Hope this helps! :)
I think your timeouts are stacking up. As soon as major gets called once, the variables itemTimer and stopTimeout get reassigned a new timeout reference. So there will be no way to clear the timeouts that were previously set. If this is the case it should be an easy fix though. Just call stopTimer as very first statement in major: function major (){ stopTimer(); var itemTime = Math.floor(Math.random() * 15000) + 2000; itemTimer = setTimeout('items()', itemTime); stopTimeout = setTimeout('major()',itemTime); }
Combine 2 function of javascript / Type script into one
I Have one Date variable, and I am updating it every second to make it live. Now here is my variable. var stationdate = new Date(data.localTime); My Javascript code to update it per second. window.setInterval(function () { stationdate = new Date(stationdate.setSeconds(stationdate.getSeconds() + 1)); }, 1000); And My Type Script code to return it to Angular UI. window.setInterval(() => this.time = stationdate, 1000); My Issue. It works perfectly if both functions are seprate. but it stops working if I combine them. see below. window.setInterval(function () { stationdate = new Date(stationdate.setSeconds(stationdate.getSeconds() + 1)); this.time = stationdate; }, 1000); AM I MISSING SOMETHING WITH FAT ARROW OF TYPE SCRIPT? What should be the proper function?
Each function has it's own this context. So your this refers to another object in the function expression. With arrow function it refers to the outer this which contains that arrow function. Use arrow syntax and there is no necessary to use window prefix behind the setInterval. setInterval(() => { stationdate = new Date(stationdate.setSeconds(stationdate.getSeconds() + 1)); this.time = stationdate; }, 1000); For more read Arrow function vs function declaration/expression - this is one of the main concepts in Javascript.
In your combination of both function your not using an arrow function, which leads to the context of this is window. Use an arrow function to keep the outer context of this. window.setInterval(() => { stationdate = new Date(stationdate.setSeconds(stationdate.getSeconds() + 1)); this.time = stationdate; }, 1000);
In your second example, this refers to the inner-scope of your function not the outer scope where your variable is most likely defined. Therefore as others have suggested, you need to use the lambda symbol. Also, since you're using AngularJS it would be preferable to use $interval instead of window.setInterval(). Note that by using $interval, a $scope.$apply() will be made to do dirty-checking if your variable has changed and then update the UI. This is not a given when using window.setInterval(). Alternatively, you can still tell $interval to not use $apply if that is something you need.
It common bug of using callbacks. All in javascript has own 'this' context (except arrow functions). Just for systems function this===undefined. So proper way is use arrow function (as it shown above). Best for modern browsers (or transpiled code). window.setInterval(() => { stationdate = new Date(stationdate.setSeconds(stationdate.getSeconds() + 1)); this.time = stationdate; }, 1000); Another way to store 'this' is binding context: window.setInterval((function () { stationdate = new Date(stationdate.setSeconds(stationdate.getSeconds() + 1)); this.time = stationdate; }).bind(this), 1000); Or more explanation: window.setInterval( (function(){console.log(this.hello);}).bind({hello:'hello!'}) , 1000);
window.setInterval( () => { stationdate = new Date(stationdate.setSeconds(stationdate.getSeconds() + 1)); this.time = stationdate; }, 1000); In your code this has wrong context. The fat arrow function is feature of ES6 and has nothing to do with TypeScript
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);
SetTimeout not functioning properly
This code is running all 21 console logs all at once. It should, however, run them one at a time at a set interval Any suggestions? var index = 1; var switchBG = function(num){ if( num < 22 ){ console.log('index' + index); console.log('num' + num); index++; function_timer(index); } }; var timer; var function_timer = function(index){ clearTimeout(timer); timer = setTimeout(switchBG(index), 10000); };
You need to pass a function as an argument to setTimeout. Try this: timer = setTimeout(function() { switchBG(index); }, 10000); Doing setTimeout(switchBG(index), 10000); basically evaluates switchBG(index) and passes its return value (which is currently undefined) to setTimeout.
When you do: setTimeout(switchBG(index), 10000); you are calling switchBG(index) immediately, and then passing it's return value (which is undefined) to setTimeout. Instead you want to pass a function reference, and then pass the additional arguments to setTimeout: setTimeout(switchBG, 10000, index); If you want to use additional arguments to setTimeout like that to work in Internet Explorer, you'll need to shim it. It will work in every other browser without a shim. If you want to support IE and don't want to use the shim, you can create an extra anonymous function to achieve the same result: setTimeout(function(){ switchBG(index); }, 10000);