2
var data = [{offset: 2000, str:'foo'}, {offset: 4000, str:'bar'}];
for (var i=0; i<data.length; i++) {
 var x = data[i];
 setTimeout(function(){printStuff(x.str)}, x.offset);
}
function printStuff(str) {
 console.log(str);
}

I was expecting to get printStuff('foo') at 2000 ms offset and printStuff('bar') at 4000 ms offset but instead it prints 'bar' both times. I've no idea what's going on, help please.

asked Jul 6, 2012 at 14:17
1
  • it's a scoping issue; when your printStuff finally runs, x has been reassigned to {offset:4000,str:'bar'} Commented Jul 6, 2012 at 14:22

3 Answers 3

3

Do this :

for (var i = 0; i < data.length; i++) {
 (function (x) {
 setTimeout(function () {
 printStuff(x.str)
 }, x.offset);
 })(data[i]);
}

Your problem is that x has changed in the closure when the function is called.

Esailija
140k24 gold badges280 silver badges328 bronze badges
answered Jul 6, 2012 at 14:19
Sign up to request clarification or add additional context in comments.

Comments

2

You can use functional iteration that gives a closure for free:

data.forEach( function( x ) {
 setTimeout( printStuff.bind(null, x.str), x.offset );
});

Shims for all in case oldIE support is required:

forEach

bind

answered Jul 6, 2012 at 14:24

2 Comments

I didn't knew this new and interesting function. Do you have precision about the compatibility (including mobiles) ?
@dystroy the compatibility and user-made code to make those functions work in unsupported browsers can be found in the links I gave. Roughly any browser made/patched after december 2009 should support them.
0

setTimeout does not block the code from continuing to execute, so the loop completes, and by the time the setTimeout callback is executed, the latest value for 'x' is the second object in the data array.

answered Jul 6, 2012 at 14:24

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.