SetTimeout and recursivity with cucumber - javascript

I have a function written in javascript calling itself in a recursive way :
function f(attempt){
if (attempt + 1 <= 10) {
setTimeout(f(attempt + 1),2000);
}
}
f(0);
For an unknown reason the function is effectively called 10 times but without any delay. The setTimeout seems to execute immediately the function f.
However when I do this then everything works fine :
function f(attempt){
if (attempt + 1 < 10) {
setTimeout(function(){f(attempt + 1);},2000);
}}
f(0);
Do you have an explanation ? Is is because this code is written for Cucumber testing ?

You have to pass the function as a parameter to setTimeout, that means no parenthesis at the end of f. What you are doing right now is calling f and passing it's return value to setTimeout. You can pass arguments to f as the third argument of setTimeout. Your call should look like this:
setTimeout(f, 2000, attempt + 1);

setTimeout(f(attempt + 1),2000);
This code above calls setTimeout function and instead of passing a function to call it passes the result of your f() function, it is invoked right on the spot.
setTimeout(function() { f(attempt + 1) },2000);
But in this case you are passing a reference to your function to be invoked in a 2000 seconds, so it does not evaluate the function itself on the spot.

You should write it like this.
This is an alternative way to do the check and have no private vars.
function f(){
if(++attempt<10){// not shure
setTimeout(f,2000);
}
}
var attempt=0;
f();
Demo
http://jsfiddle.net/3nm2Q/

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
}

How setTimeout works?

I have a concern with setTimeout function in javascript. when we call setTimeout function without return anything, it is okay for me. like
setTimeout(function() {
console.log("ok function called")
},2000);
here in the above example it just simply call that function after 2000ms,
And if I write this like
setTimeout(function(params) {
console.log("passed value is"+params)
},2000,55);
now it will call this function with 55 as an argument, right?
But problem is that when I call to write this like
setTimeout(function(params) {
console.log("passed value is"+params)
}(55),2000);
here function is calling with 55 as params but it is now waiting for 2000ms
And when I wrote like
setTimeout(function(params) {
console.log("passed value is "+params);
return function(){
console.log(params)
};
}(55),2000);
in this only return function is calling with 2000ms delay, the line console.log("passed value is "+params); is executing instantly
please help me get out of this problem.
One is a function. Another is a function call.
First, let's forget javascript for now. If you know any other programming language, what do you expect the two pieces of code below to do?
function a () { return 1 }
x = a;
y = a();
What do you expect x to be? 1 or a pointer to function a?
What do you expect y to be? 1 or a pointer to function a?
A function is not a function call. When you call a function it returns a value.
Now let's switch back to javascript. Whenever I get confused by a piece of code, I try to make the syntax simpler so that I can understand what's going on:
setTimeout(function() {console.log("ok function called")}, 2000);
Now, that's a compact piece of code, let's make the syntax simpler. The above code is the same as:
var a = function() {console.log("ok function called")};
setTimeout(a, 2000);
So what does that do? It will call the function a after 2 seconds.
Now let's take a look at:
setTimeout(function() {console.log("ok function called")}(), 2000);
// Note this ----------^^
That's the same as:
var b = function() {console.log("ok function called")}();
setTimeout(b, 2000);
which can further be simplified to:
var a = function() {console.log("ok function called")};
var b = a();
setTimeout(b, 2000);
So I hope you see what you're really passing to setTimeout. You're passing the return value of the function, not the function.
When you write
setTimeout(function (params) { return something; }(55), 2000);
what actually happens is something like this:
var _temp_func = function (params) { return something; };
var _temp = _temp_func(55);
setTimeout(_temp, 2000);
The anonymous function you have as a parameter to setTimeout is evaluated immediately, even before the call to setTimeout itself. In contrast to that, the actual parameter that ends up in _temp here is called with a delay. This is what happens in your last example.
setTimeout takes only function name without parenthesis.
correct syntax : setTimeout(Helloworld) - here you are setting function
incorrect syntax : setTimeout(HelloWorld()) - here you are calling function
or non IIFE function.
It's an IIFE that you are passing hence it is getting called immediately.
setTimeout(function (params) { return something; }(55), 2000);

Trouble understanding closure details - setTimeout within for loop

I'm having trouble understanding why the first snippet below executes all five console.log's quickly, while the second snippet executes the console.log's one second apart.
I understand that a closure (aka a function + the scope in which it was declared) is needed to "close" over the value of i at various points in the for loop.
I understand that in the first snippet, the innermost function is immediately invoked, while the second snippet's innermost function is not immediately invoked.
And yet, it does not feel clear to me what is actually happening.
Some questions:
In the first snippet, is the innermost function executing over separate ticks?
In the first snippet, why does the innermost function execute so quickly?
In the second snippet, why does the innermost function execute over one second intervals?
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
(function () {
console.log(x)
})(i)
})(i),
i * 1000
)
}
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
return (function () {
console.log(x)
})
})(i),
i * 1000
)
}
Note: I do understand that using let makes this much easier, but I'm trying to understand this in terms of closures.
for (let i = 1; i <= 5; i++) {
setTimeout(
function () {
console.log(i)
},
i * 1000
)
}
This has nothing to do with the mechanics of closures. This is 100% caused by how functions work.
Now, let's tease apart the two different functions. For clarity I'm going to completely remove the for loop:
1:
var i = 1; // We simply hardcode `i` for this demo.
function a (x) {
(function(){
console.log(x);
})(i); // immediately call this function
// THIS IS THE MOST IMPORTANT PART OF THE CODE
// Yes, this space with no code at all at the end of
// this function is the MOST IMPORTANT part of the code.
// This absence of code represents "return undefined".
// All functions that return nothing returns undefined.
}
setTimeout(a(i),i * 1000);
Note: remember that a() returns undefined. So the setTimeout is actually:
setTimeout(undefined,1000);
"Helpfully", if you pass undefined to setTimeout it will gracefully accept it and not generate any errors.
It should also be obvious that you directly call console.log when calling a().
Now let's look at the other code:
2:
var i = 1;
function b (x) {
return (function () {
console.log(x)
}) // <--- note you are not calling the inner function at all
}
setTimeout(b(i), i * 1000);
Note that since b() returns a function setTimeout will call the function returned by b() (the one that calls console.log) after 1 second.
The difference here is less about how closures work and more about how setTimeoute() works. setTimeout will invoke the passed in function sometime after the time passed in. So you pass it a function:
setTimeout(someFunction, 1000)
And in a 1000 milliseconds or so it executes someFunction()
In the first example you are executing the functions before setTimout ever has a chance to by immediately calling someFunction(). By the time setTimeout gets around to it, it doesn't have a function to call -- just the return values of the function you already called. The functions are being called synchronously on the current tick.
You can think of it like passing a callback. If you pass a callback to a function like this someFunction(null, cb) it can execute it later with cb(), but if you pass someFunction(null, cb()) it will receive the return value of cb rather than cb itself. If that's a function it will call that.
In the second example you immediately execute the outside function, but return a function the setTimeout can call later. That is what it does, which is why this works as expected.
It is simple, but tricky :)
In first example, your creating and executing anonymous functions. Then you return undefined to the setTimeout. setTimeout will execute nothing. Thats why it executes quickly.
In second example, your creating and executing an anonymous function that creates another anonymous function and return it to setTimeout. Then setTimeout will execute it.
See my comments:
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
(function () {
console.log(x)
})(i) -> create and EXECUTE anonymous function (execute it right away)
})(i), -> create and execute anonymous function. returns undefined
i * 1000
)
}
for (var i = 1; i <= 5; i++) {
setTimeout(
(function (x) {
return (function () {
console.log(x)
})
})(i), -> create and execute anonymous function. returns a new function
i * 1000
)
}

Global variable is logged as undefined when passed as parameter to setTimeout callback function

I have some JS code as below:
var x = self.someAJAXResponseJSON; // x has some object value here.
setTimeout(function(x){
console.log("In setTimeout:", x); // But x is undefined here
}, 1000);
So I want to pass x to the setTimeout callback function. But I am getting x as undefined inside the setTimeout.
What am I doing wrong?
Any idea how to fix a similar issue using Dojo.js?
setTimeout(dojo.hitch(this, function(){
this.executeSomeFunction(x); // What should this be?
console.log("In setTimeout:", x); // But x is undefined here
}), 1000);
Alternatively you can do it without creating a closure.
function myFunction(str1, str2) {
alert(str1); //hello
alert(str2); //world
}
window.setTimeout(myFunction, 10, 'hello', 'world');
But note it doesn't work on IE < 10 according to MDN.
When setTimeout invokes the callback, it doesn't pass any arguments (by default); that is, the argument x is undefined when the callback is invoked.
If you remove the parameter x, x in the function body won't refer to the undefined parameter but instead to the variable you defined outside the call to setTimeout().
var x = "hello";
setTimeout(function () { //note: no 'x' parameter
console.log("setTimeout ... : " + x);
}, 1000);
Alternatively, if it must be a parameter, you can pass it as an argument to setTimeout (do yourself a favor and name it differently, though):
var x = "hello";
setTimeout(function (y) {
console.log("setTimeout ... : " + y);
}, 1000, x);
Ran into this myself and looked at the Node docs, arguments to be passed into the function come in as a 3rd(or more) parameter to the setTimeout call so...
myfunc = function(x){console.log(x)};
x = "test";
setTimeout(myfunc,100,x);
Worked for me.
In your code, console.log(x)refers to the x parameter of the callback function.
Just omit it from function signature, and you'll be fine:
setTimeout(function(){
console.log("setTimeout ... : " + x); // now x is the global x
}, 1000);
It is because the function is called without passing it any argument: so x is undefined.
You should wrap it in a closure if you are willing to call it with different parameters for x:
var x = self.someAJAXResponseJSON; // x has some object value here
setTimeout((function(y){
return(function() {
console.log("setTimeout ... : " + y);
})
})(x), 1000);
setTimeout method is designed to take function or code snippet as its first argument but in you case you have taken an anonymous function with parameter x and which is called without taking any argument so it shows is undefined because there is no concrete function defined that takes x. What you can do is you can first define the function you want to call and then just call it in setTimeout method. See following code snippet:
var x = self.someAJAXResponseJSON;
function mylog(x){
console.log("setTimeout ... : " + x);
}
setTimeOut(mylog(x),1000);

Javascript function call into loop each time

I have function called rotator(id): this function animate div and I can called this function with different id for animate different elements
Actually I use 5 differents id , 1,2,3,4,5
And for call I need put :
rotador(1);rotador(2);rotador(3);rotador(4);rotador(5);
The problem it´s that I want to rotate in automatic mode. For this I think to use this
for (i=0;i<=5;i++) {
setTimeout(rotador(i),2000);
}
But it doesn't work because it animates all in the same time, no let firt execute the first and continue before of first go second , etc , etc and when go the end or number 5 start other time in one
My problem it´s this if you can help me THANKS !!! :) Regards
You are actually calling the rodator(i) function, and schedule for execution after 2 seconds the result of the rodator. In other words, your code is now equalent to:
for (i=0;i<=5;i++) {
var result = rotador(i);
setTimeout(result,2000);
}
You can accomplish this either by creating a function for the callback:
for (i=0;i<=5;i++) {
setTimeout((function(i){
return function(){
rotador(i);
}
})(i),2000 * i);
}
or you can call the next rodator in the rotador function itself:
var rotador = function(i){
// your code
if (i < 5) {
setTimeout(function(){rotaror(i + 1);}, 2000);
}
}
Note: the closure in the second example is needed to call the function with the correct value of i. We are creating an anonymous function, and create i as a local scope variable, which value won't be mutated by the outerscope changes. (we can rename i to n in the local scope, if this would be more readable). Otherwise the value of i will be 5 each time rotador is called, as the value of i would be modified before the actual function call.
since setTimeout() does not wait for the function to be executed before continuing, you have to set the delay to a different value for different items, something like 2000 * (i + 1) instead of just 2000
EDIT: yes, and you need the callback as Darhazer suggests
rotationStep(1);
function rotador(id)
{
console.log(id);
}
function rotationStep( currentId )
{
rotador(currentId);
var nextId = currentId<5 ? currentId+1 : 1;
setTimeout(function(){ rotationStep(nextId) },2000); //anonymous function is a way to pass parameter in IE
}
Use a callback:
setTimeout(function() {
rotador(i)
}, 2000)

Categories

Resources