0

I was having some logic problem with the while loop in JavaScript. So basically I am trying to loop a list of coordinate, at each coordinate, I am executing the moveNext() which will plot a marker and loop until the while loop ends. Here is the code:

var k = 1;
        while(k < pointArr.length){
            var coordx = pointArr[k].x;
            var coordy = pointArr[k].y;
            window.setTimeout(function(){
                moveNext(coordx, coordy, k);   
            },500);
            k++;
        }

And the moveNext() which plot a marker onto the map if the parameter k is larger than global counter variable:

var counter = 0;
function moveNext(coordx, coordy, k){
if(k > counter){
    console.log(coordx);
    console.log(coordy);
    map.graphics.clear();
    var point = new esri.geometry.Point({ "x": coordx, "y": coordy, "spatialReference": { "wkid": 3414 } });
    var symbol = new esri.symbol.PictureMarkerSymbol('img/transportation/currentLoc.GIF', 30, 30);
    var PointGraphic = new esri.Graphic(point, symbol);
    map.graphics.add(PointGraphic);

    var graphic = PointGraphic;
    graphic.setSymbol(symbol);
    map.graphics.add(graphic);

    counter++;
}
}

However, with these codes, it does not execute the setTimeout point by point plotting marker onto the map. Instead, it loops all the way until the end of the while loop and plot the last marker there. Any guides?

Thanks in advance.

Andy Brown
  • 18,961
  • 3
  • 52
  • 62
QWERTY
  • 2,303
  • 9
  • 44
  • 85

2 Answers2

1

The issue is caused because setTimeout executes the method passed after the execution of the current method ends. And because the scope of the method passed to setTimeout encloses over the scope of the current method (see closure) your moveNext method will get only the last values of coordX and coordY.

You can fix this by adding the setTimeout call into an immediate function. This way, the parameters coordX and coordY will remain the same as the function executes right away and sets the timeout for further execution.

var pointArr = [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 3}];

var k = 0;
while(k < pointArr.length){
  var coordx = pointArr[k].x;
  var coordy = pointArr[k].y;

  (function(coordx, coordy, k) {
    window.setTimeout(function(){
      moveNext(coordx, coordy, k);   
    },500);
  })(coordx, coordy, k);

  k++;
}

function moveNext(x, y, k) {
  alert(x + ' - ' + y + ' - ' + k);
}

If you want to wait 500 ms between each plot you could do something like this:

var pointArr = [{x: 1, y: 2}, {x: 2, y: 2}, {x: 3, y: 3}];

function moveToNextPoint(k) {
  if(k < pointArr.length) {
    var coordx = pointArr[k].x;
    var coordy = pointArr[k].y;
    moveNext(coordx, coordy, k);

    setTimeout(function() {
      moveToNextPoint(k + 1);
    }, 500);
  }
}


function moveNext(x, y, k) {
  alert(x + ' - ' + y + ' - ' + k);
}

moveToNextPoint(0);
Community
  • 1
  • 1
Valentin S.
  • 504
  • 2
  • 10
  • Nope, it does not work. When I print out the coordx and coordy in moveNext(), I am getting a list of coordinate but it does not plot step by step onto the map. Any ideas? – QWERTY Jan 15 '15 at 09:42
  • It works on me. Run the code in my answer in a javascript console. – Valentin S. Jan 15 '15 at 09:48
  • But I wanted it works this way, there is 10 points for the route. For first point, I plot a marker, I stayed for 10 seconds before moving to another point. Currently the solution is like I plot the marker after 500 then loop thru each point without stopping for a few seconds. Any ideas? – QWERTY Jan 15 '15 at 09:56
  • See my answer. I hope I understood what you want – Valentin S. Jan 15 '15 at 10:08
1

maybe if you want to use forEach instead of while

timeout = 500;
pointArr.forEach(function(coord,index){
    setTimeout(function(){
        moveNext(coord.x, coord.y, index);
    }, timeout * index);
});

hope it help..

ps: I don't like to use while because it has possibility to infinite loop if you wrong fill the condition

Park Dong Gun
  • 114
  • 1
  • 4