4

Experts. Javascript not producing desired delay effect.
From other questions, on SO I got to know that, problem is with settimeout and the way I am using it. But still I am not able to comprehend, how Settimeout works. So I am putting code here. Need to use Javascript only, because of knowledge purpose.
Actually I am trying to clear my concepts about this, closure in javascript. Are they kind of twisted things of Javascript?

var objImg = new Object();
var h;
var w;

var no = 100;
while (no != 500) {
    setTimeout(function () {
        size(no, no);
    }, 2000);

    /* it's get executed once, instead of repeating with while loop
    Does it leave loop in mid? I get image with 500px height and
    width, but effect is not acheived.
    */

    no = no + 50;
}

function size(h, w) {
    var objImg = document.getElementsByName('ford').item(0);
    objImg.style.height = h + 'px';
    objImg.style.width = w + 'px';
}
hexacyanide
  • 88,222
  • 31
  • 159
  • 162
msinfo
  • 1,147
  • 6
  • 21
  • 39
  • your while loop is working normal.I've tested it on chrome console. – Ramin Omrani Feb 09 '13 at 20:34
  • @ramin omrani - true? but Image is not getting resized with delay effect of 2 sec. I know I have messed with SetTimeout, but don't know its inner working fully yet. – msinfo Feb 09 '13 at 20:45

3 Answers3

4

You have two problems :

  • no will have the value of end of loop when the callback is called
  • you're programming all your timeouts 2000 ms from the same time, the time the loop run.

Here's how you could fix that :

var t = 0
while (no != 500) {
   (function(no) {
      t += 2000;
      setTimeout(function() { size(no,no);} ,t);
   })(no);
   no  = no+50; // could be written no += 50
}

The immediately executed function creates a scope which protects the value of no.


A little explanation about (function(no) { :

The scope of a variable is either

  • the global scope
  • a function

The code above could have been written as

var t = 0
while (no != 500) {
   (function(no2) {
      t += 2000;
      setTimeout(function() { size(no2,no2);} ,t);
   })(no);
   no += 50;
}

Here it's probably more clear that we have two variables :

  • no, whose value changes with each iteration and is 500 when the timeouts are called
  • no2, in fact one variable no2 per call of the inner anonymous function

Each time the inner anonymous function is called, it declares a new no2 variable, whose value is no at the time of call (during iteration). This variable no2 is thus protected and is used by the callback given to setTimeout.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
3

Why not just use setInterval() instead?

var objImg = new Object();
var h;
var w;

var no = 100;
var myInterval = window.setInterval(function() {
    size(no, no);
    no = no + 50;
    if (no >= 500) clearInterval(myInterval);
}, 2000);

function size(h, w) {
    var objImg = document.getElementsByName('ford').item(0);
    objImg.style.height = h + 'px';
    objImg.style.width = w + 'px';
}
daleyjem
  • 2,335
  • 1
  • 23
  • 34
  • he he he :-) it works your way. Actually I wrote above test code to test my knowledge about settimeout and other things, and here I learnt anothe way of doing it. Would be marking it as answer as soon as someone explains what happened to settimeout in my code. Thanks. – msinfo Feb 09 '13 at 20:50
  • Your code doesn't work the way you think because you're thinking that each setTimeout() will get called once the time passes from the previous setTimeout(). But that isn't so. All of these setTimeout()'s are going to get called immediately at the same time. – daleyjem Feb 09 '13 at 23:53
  • Oh! I see, true I was thinking the way you figured out. But oops! since @dystroy gave solution with settimeout option, and he edited multiple times his answer to inform me. I am accepting his answer and up-voting yours. – msinfo Feb 09 '13 at 23:58
  • And like dystroy said... By the time all of those setTimeout()'s get called (which will be at the same time), the value of "no" would have been incremented up to 500 (which would have happened in a matter of milliseconds as soon as the code executed). – daleyjem Feb 09 '13 at 23:58
0

Your problem is with your size() function syntax & algorithm:

var objImg = new Object();
var h;
var w;

var no = 100;

var int = window.setInterval(function () {
    size(no,no);
    no += 50;
},2000)

function size(h, w) {
    if (h == 500){
        window.clearInterval(int);
        return;
    }
    var height = h + 'px';
    var width = w + 'px';
    document.getElementsByName('ford').item(0).style.height = height;
    document.getElementsByName('ford').item(0).style.width = width;
}

http://jsfiddle.net/AQtNY/2/

Ramin Omrani
  • 3,673
  • 8
  • 34
  • 60