Chrome extension: How to settimeout with update [duplicate] - javascript

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
}

Related

TypeError: "listener" argument must be a function. Using npm pixelmatch in node JS [duplicate]

How do I pass a function as a parameter without the function executing in the "parent" function or using eval()? (Since I've read that it's insecure.)
I have this:
addContact(entityId, refreshContactList());
It works, but the problem is that refreshContactList fires when the function is called, rather than when it's used in the function.
I could get around it using eval(), but it's not the best practice, according to what I've read. How can I pass a function as a parameter in JavaScript?
You just need to remove the parenthesis:
addContact(entityId, refreshContactList);
This then passes the function without executing it first.
Here is an example:
function addContact(id, refreshCallback) {
refreshCallback();
// You can also pass arguments if you need to
// refreshCallback(id);
}
function refreshContactList() {
alert('Hello World');
}
addContact(1, refreshContactList);
If you want to pass a function, just reference it by name without the parentheses:
function foo(x) {
alert(x);
}
function bar(func) {
func("Hello World!");
}
//alerts "Hello World!"
bar(foo);
But sometimes you might want to pass a function with arguments included, but not have it called until the callback is invoked. To do this, when calling it, just wrap it in an anonymous function, like this:
function foo(x) {
alert(x);
}
function bar(func) {
func();
}
//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });
If you prefer, you could also use the apply function and have a third parameter that is an array of the arguments, like such:
function eat(food1, food2) {
alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args) {
//do stuff
//...
//execute callback when finished
callback.apply(this, args);
}
//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]);
Example 1:
funct("z", function (x) { return x; });
function funct(a, foo){
foo(a) // this will return a
}
Example 2:
function foodemo(value){
return 'hello '+value;
}
function funct(a, foo){
alert(foo(a));
}
//call funct
funct('world!',foodemo); //=> 'hello world!'
look at this
To pass the function as parameter, simply remove the brackets!
function ToBeCalled(){
alert("I was called");
}
function iNeedParameter( paramFunc) {
//it is a good idea to check if the parameter is actually not null
//and that it is a function
if (paramFunc && (typeof paramFunc == "function")) {
paramFunc();
}
}
//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled);
The idea behind this is that a function is quite similar to a variable. Instead of writing
function ToBeCalled() { /* something */ }
you might as well write
var ToBeCalledVariable = function () { /* something */ }
There are minor differences between the two, but anyway - both of them are valid ways to define a function.
Now, if you define a function and explicitly assign it to a variable, it seems quite logical, that you can pass it as parameter to another function, and you don't need brackets:
anotherFunction(ToBeCalledVariable);
There is a phrase amongst JavaScript programmers: "Eval is Evil" so try to avoid it at all costs!
In addition to Steve Fenton's answer, you can also pass functions directly.
function addContact(entity, refreshFn) {
refreshFn();
}
function callAddContact() {
addContact("entity", function() { DoThis(); });
}
I chopped all my hair off with that issue. I couldn't make the examples above working, so I ended like :
function foo(blabla){
var func = new Function(blabla);
func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");
And that's working like a charm ... for what I needed at least. Hope it might help some.
I suggest to put the parameters in an array, and then split them up using the .apply() function. So now we can easily pass a function with lots of parameters and execute it in a simple way.
function addContact(parameters, refreshCallback) {
refreshCallback.apply(this, parameters);
}
function refreshContactList(int, int, string) {
alert(int + int);
console.log(string);
}
addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
You can also use eval() to do the same thing.
//A function to call
function needToBeCalled(p1, p2)
{
alert(p1+"="+p2);
}
//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
eval(aFunction + "("+params+")");
}
//A function Call
callAnotherFunction("needToBeCalled", "10,20");
That's it. I was also looking for this solution and tried solutions provided in other answers but finally got it work from above example.
Here it's another approach :
function a(first,second)
{
return (second)(first);
}
a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world
In fact, seems like a bit complicated, is not.
get method as a parameter:
function JS_method(_callBack) {
_callBack("called");
}
You can give as a parameter method:
JS_method(function (d) {
//Finally this will work.
alert(d)
});
The other answers do an excellent job describing what's going on, but one important "gotcha" is to make sure that whatever you pass through is indeed a reference to a function.
For instance, if you pass through a string instead of a function you'll get an error:
function function1(my_function_parameter){
my_function_parameter();
}
function function2(){
alert('Hello world');
}
function1(function2); //This will work
function1("function2"); //This breaks!
See JsFiddle
Some time when you need to deal with event handler so need to pass event too as an argument , most of the modern library like react, angular might need this.
I need to override OnSubmit function(function from third party library) with some custom validation on reactjs and I passed the function and event both like below
ORIGINALLY
<button className="img-submit" type="button" onClick=
{onSubmit}>Upload Image</button>
MADE A NEW FUNCTION upload and called passed onSubmit and event as arguments
<button className="img-submit" type="button" onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>
upload(event,fn){
//custom codes are done here
fn(event);
}
By using ES6:
const invoke = (callback) => {
callback()
}
invoke(()=>{
console.log("Hello World");
})
If you can pass your whole function as string, this code may help you.
convertToFunc( "runThis('Micheal')" )
function convertToFunc( str) {
new Function( str )()
}
function runThis( name ){
console.log("Hello", name) // prints Hello Micheal
}
You can use a JSON as well to store and send JS functions.
Check the following:
var myJSON =
{
"myFunc1" : function (){
alert("a");
},
"myFunc2" : function (functionParameter){
functionParameter();
}
}
function main(){
myJSON.myFunc2(myJSON.myFunc1);
}
This will print 'a'.
The following has the same effect with the above:
var myFunc1 = function (){
alert('a');
}
var myFunc2 = function (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
Which is also has the same effect with the following:
function myFunc1(){
alert('a');
}
function myFunc2 (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
And a object paradigm using Class as object prototype:
function Class(){
this.myFunc1 = function(msg){
alert(msg);
}
this.myFunc2 = function(callBackParameter){
callBackParameter('message');
}
}
function main(){
var myClass = new Class();
myClass.myFunc2(myClass.myFunc1);
}

Can I put a method as the argument in the setInterval function?

Preety straight forward question, though I can't find the answer anywhere
I tried these two ways:
setInterval(function(){object/*or this*/.method()},500)
and
setInterval('object/*or this*/.method()',500)
setInterval in fact expects a method as the first argument, though there is an alternative syntax where the first argument can be a string of code (not recommended by most)
If you're having issues with that code, it may have to do with the scope of 'this'
setInterval(function(){this.method()},500)
In the above code, 'this' will refer to the closure itself, and wouldn't be the same as 'this.method' occurring outside of that closure. For example, the following would work:
function MyClass() {
this.thingy = 'yep this is a thingy'
}
var myClass = new MyClass()
// Will log 'MyClass yep this is a thingy'
setInterval(function() { console.log('MyClass', myClass.thingy) }, 1000)
Whereas the following will not work (presuming instantiating the object and calling foo()):
function MyOtherClass() {
this.thingy = 'also a thingy'
}
// Will log 'MyOtherClass undefined'
MyOtherClass.prototype.foo = function() {
setInterval(function() { console.log('MyOtherClass', this.thingy) }, 1000)
}
The second example will work if we get around using 'this' within the closure (presuming instantiating the object and calling bar()):
MyOtherClass.prototype.bar = function() {
var that = this
setInterval(function() { console.log('MyOtherClass', that.thingy) }, 1000)
}
Also be sure that setInterval is being passed the name of a function:
setInterval(someFunction, 500)
rather than executing a function as an argument
setInterval(someFunction(), 500)
This last line of code is usually a mistake, unless someFunction() returns a function itself ;)
The difference between your 2 ways for passing a function to setInterval is whether you want to pass your function as refrence of just copy of it. Allow me to explain it by example:
-1 Referring(demo):
var obj = {
testMethod: function () {
console.log('function (testMethod): intial output');
}
}
setInterval(function () {
obj.testMethod()
}, 1000);
obj.testMethod = function () {
console.log('function (testMethod): changed output');
}
when you run this code, the result 'll be execution of the modified version of testMethod. Because here you dont copy the function! Instead, you refer to it. So whenever function implementation is changed, the last modified version is executed.
-2 Copying(demo):
var obj = {
testMethod: function () {
console.log('function (testMethod): intial output');
}
}
setInterval(obj.testMethod, 1000);
obj.testMethod = function () {
console.log('function (testMethod): changed output');
}
Here all you do is you are passing a copy of the last defined version of the function testMethod to setInterval. So whatever changes you do to testMethod, the result of setInterval will not be changed.

Why do I have to enclose a Javascript function call in an anonymous function for it to not be called immediately?

I have this Javascript function:
function Card(term, def, terms, curTerm) {
this.term = term;
this.def = def;
this.terms = terms;
this.curTerm = curTerm;
this.show = function() {
that = this;
var html = createCard(that.term, that.def);
$('body').append(html);
$('input[type=text]').focus();
$('.answer').on('click', function(event) {
event.preventDefault();
answer = $(this).parent().serializeArray()[0].value;
// answer correct
if (that.term === answer) {
$('.card').addClass('correct');
$('form').replaceWith('<h2>Correct! ' + that.term + '</h2>');
setTimeout(function () {that.destroy(terms, curTerm + 1);}, 1500);
// answer incorrect
} else {
$('.card').addClass('incorrect');
$('form').replaceWith('<h2>Incorrect! ' + that.term + '</h2>');
setTimeout(function () {that.destroy(terms, curTerm);}, 1500);
}
});
};
The line I am having issues with is setTimeout(function () {that.destroy(terms, curTerm + 1);}, 1500);. Originally I had setTimeout(that.destroy(terms, curTerm + 1), 1500);, but it didn't set the timeout it just called that.destroy. Why does it not call it immediately when put in the anonymous function? Does this have anything to do with closures? because it seems like I am having to create a closure, but I haven't figured out enough about them to know for sure.
Any thoughts would be appreciated.
In your first setTimeout() call, this:
that.destroy(terms, curTerm + 1)
is a function call expression. It's evaluated in order to build the set of parameter values to call setTimeout().
When you wrap it in an anonymous function, that (anonymous) function is not called, because you don't suffix it with the function call operator — the parenthesized list of parameters.
Thus: an expression of the form
something ( p1, p2, ... pn )
means to invoke the function referenced by "something" after evaluating each of the parameters in the argument list, and then use that value as the larger expression context proceeds. It always means that in JavaScript. There's no syntax to say "here's the function I want you to call later, and some parameters to pass". (There's a function to do that now — .bind() on the Function prototype — but no special syntax.)
This is just part of the JavaScript syntax.
function name() {} declares a function and name() calls it. You can also call anonymous functions immediately with the syntax (function (){})().
Also note that you can pass function names where an anonymous function would otherwise be appropriate, as in:
setTimeout(that.destroy, 1500)
Of course you can't change the arguments in that case.
When the JavaScript interpreter sees someFunction(param), it immediately calls the method someFunction and passes it the parameter param. In other words, when you do:
setTimeout(someFunction(param), 1000);
... you're passing setTimeout the result of someFunction(param). You can instead pass someFunction as a first-class member like this:
setTimeout(someFunction, 1000, param);
This way, you're passing setTimeout the definition of someFunction. Beware that passing param in this case won't work in IE.
Also, see http://www.helephant.com/2008/08/19/functions-are-first-class-objects-in-javascript/.

Pass a JavaScript function as parameter

How do I pass a function as a parameter without the function executing in the "parent" function or using eval()? (Since I've read that it's insecure.)
I have this:
addContact(entityId, refreshContactList());
It works, but the problem is that refreshContactList fires when the function is called, rather than when it's used in the function.
I could get around it using eval(), but it's not the best practice, according to what I've read. How can I pass a function as a parameter in JavaScript?
You just need to remove the parenthesis:
addContact(entityId, refreshContactList);
This then passes the function without executing it first.
Here is an example:
function addContact(id, refreshCallback) {
refreshCallback();
// You can also pass arguments if you need to
// refreshCallback(id);
}
function refreshContactList() {
alert('Hello World');
}
addContact(1, refreshContactList);
If you want to pass a function, just reference it by name without the parentheses:
function foo(x) {
alert(x);
}
function bar(func) {
func("Hello World!");
}
//alerts "Hello World!"
bar(foo);
But sometimes you might want to pass a function with arguments included, but not have it called until the callback is invoked. To do this, when calling it, just wrap it in an anonymous function, like this:
function foo(x) {
alert(x);
}
function bar(func) {
func();
}
//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });
If you prefer, you could also use the apply function and have a third parameter that is an array of the arguments, like such:
function eat(food1, food2) {
alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args) {
//do stuff
//...
//execute callback when finished
callback.apply(this, args);
}
//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]);
Example 1:
funct("z", function (x) { return x; });
function funct(a, foo){
foo(a) // this will return a
}
Example 2:
function foodemo(value){
return 'hello '+value;
}
function funct(a, foo){
alert(foo(a));
}
//call funct
funct('world!',foodemo); //=> 'hello world!'
look at this
To pass the function as parameter, simply remove the brackets!
function ToBeCalled(){
alert("I was called");
}
function iNeedParameter( paramFunc) {
//it is a good idea to check if the parameter is actually not null
//and that it is a function
if (paramFunc && (typeof paramFunc == "function")) {
paramFunc();
}
}
//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled);
The idea behind this is that a function is quite similar to a variable. Instead of writing
function ToBeCalled() { /* something */ }
you might as well write
var ToBeCalledVariable = function () { /* something */ }
There are minor differences between the two, but anyway - both of them are valid ways to define a function.
Now, if you define a function and explicitly assign it to a variable, it seems quite logical, that you can pass it as parameter to another function, and you don't need brackets:
anotherFunction(ToBeCalledVariable);
There is a phrase amongst JavaScript programmers: "Eval is Evil" so try to avoid it at all costs!
In addition to Steve Fenton's answer, you can also pass functions directly.
function addContact(entity, refreshFn) {
refreshFn();
}
function callAddContact() {
addContact("entity", function() { DoThis(); });
}
I chopped all my hair off with that issue. I couldn't make the examples above working, so I ended like :
function foo(blabla){
var func = new Function(blabla);
func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");
And that's working like a charm ... for what I needed at least. Hope it might help some.
I suggest to put the parameters in an array, and then split them up using the .apply() function. So now we can easily pass a function with lots of parameters and execute it in a simple way.
function addContact(parameters, refreshCallback) {
refreshCallback.apply(this, parameters);
}
function refreshContactList(int, int, string) {
alert(int + int);
console.log(string);
}
addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
You can also use eval() to do the same thing.
//A function to call
function needToBeCalled(p1, p2)
{
alert(p1+"="+p2);
}
//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
eval(aFunction + "("+params+")");
}
//A function Call
callAnotherFunction("needToBeCalled", "10,20");
That's it. I was also looking for this solution and tried solutions provided in other answers but finally got it work from above example.
Here it's another approach :
function a(first,second)
{
return (second)(first);
}
a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world
In fact, seems like a bit complicated, is not.
get method as a parameter:
function JS_method(_callBack) {
_callBack("called");
}
You can give as a parameter method:
JS_method(function (d) {
//Finally this will work.
alert(d)
});
The other answers do an excellent job describing what's going on, but one important "gotcha" is to make sure that whatever you pass through is indeed a reference to a function.
For instance, if you pass through a string instead of a function you'll get an error:
function function1(my_function_parameter){
my_function_parameter();
}
function function2(){
alert('Hello world');
}
function1(function2); //This will work
function1("function2"); //This breaks!
See JsFiddle
Some time when you need to deal with event handler so need to pass event too as an argument , most of the modern library like react, angular might need this.
I need to override OnSubmit function(function from third party library) with some custom validation on reactjs and I passed the function and event both like below
ORIGINALLY
<button className="img-submit" type="button" onClick=
{onSubmit}>Upload Image</button>
MADE A NEW FUNCTION upload and called passed onSubmit and event as arguments
<button className="img-submit" type="button" onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>
upload(event,fn){
//custom codes are done here
fn(event);
}
By using ES6:
const invoke = (callback) => {
callback()
}
invoke(()=>{
console.log("Hello World");
})
If you can pass your whole function as string, this code may help you.
convertToFunc( "runThis('Micheal')" )
function convertToFunc( str) {
new Function( str )()
}
function runThis( name ){
console.log("Hello", name) // prints Hello Micheal
}
You can use a JSON as well to store and send JS functions.
Check the following:
var myJSON =
{
"myFunc1" : function (){
alert("a");
},
"myFunc2" : function (functionParameter){
functionParameter();
}
}
function main(){
myJSON.myFunc2(myJSON.myFunc1);
}
This will print 'a'.
The following has the same effect with the above:
var myFunc1 = function (){
alert('a');
}
var myFunc2 = function (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
Which is also has the same effect with the following:
function myFunc1(){
alert('a');
}
function myFunc2 (functionParameter){
functionParameter();
}
function main(){
myFunc2(myFunc1);
}
And a object paradigm using Class as object prototype:
function Class(){
this.myFunc1 = function(msg){
alert(msg);
}
this.myFunc2 = function(callBackParameter){
callBackParameter('message');
}
}
function main(){
var myClass = new Class();
myClass.myFunc2(myClass.myFunc1);
}

Defining and calling function in one step

Is there a way in Javascript to define a function and immediately call it, in a way that allows it to be reused?
I know you can do one-off anonymous functions:
(function(i) {
var product = i * i;
console.log(product);
// Can't recurse here because there's no (ECMA standard) way for the
// function to refer to itself
}(2)); // logs 4
Or you can name a function then call it afterwards:
function powers(i) {
var product = i * i;
console.log(i * i);
if (product < 1e6) { powers(product) };
}
powers(2); // Logs 4, 16, 256...
But is there a cleaner way of defining and calling a function in one go? Sort of like a hybrid of both examples?
Not being able to do this isn't preventing me from doing anything, but it feels like it would be a nice expressive way to write recursive functions or functions that need to be run on $(document).ready() but also later when situations change, etc.
You can try:
(window.powers = function(i) {
/*Code here*/
alert('test : ' + i);
})(2);
Click
Working link : http://jsfiddle.net/SqBp8/
It gets called on load, and I have added it to an anchor tag to change the parameter and alert.
If all you want is access the function within its own body, you can simply specify a name after the function keyword:
> (function fac (n) {
return (n === 0 ? 1 : n*fac(n-1));
})(10)
3628800
This is a standard feature (see ECMA-262, ed. 5.1, p. 98).
All the answers here are close to what you want, but have a few problems (adding it to the global scope, not actually calling it, etc). This combines a few examples on this page (although it unfortunately requires you to remember arguments.callee):
var test = (function() {
alert('hi');
return arguments.callee;
})();
Later, you can call it:
test();
If you don't care about the return value, you can do this.
var powers = function powers(i) {
var product = i * i;
console.log(i * i);
if (product < 1e6) { powers(product) };
return powers;
}(2);

Categories