yarek
yarek

Reputation: 12044

js: how to stop a loop after 1 second?

I try to write a function that shakes/nudges a window popup

this.nudge = function() {
    var stopped = false;
    var x=10;
    setTimeout(function() {
        stopped = true;
    },1000);

    for (i=0;;i++){
        if (stopped) break;
        window.moveBy(0,x)
        window.moveBy(x,0)
        window.moveBy(0,-x)
        window.moveBy(-x,0)
   }
}

Problem is : it never stops !

Upvotes: 2

Views: 2601

Answers (3)

Vladimir
Vladimir

Reputation: 342

Maybe you need something lie this :

this.nudge = function() {
    var x=10;
    var ts = Date.now();
    while(Date.now()-ts<1000){
        window.moveBy(0,x)
        window.moveBy(x,0)
        window.moveBy(0,-x)
        window.moveBy(-x,0)
   }
}

Upvotes: 0

Vladimir
Vladimir

Reputation: 342

What do you think about such solution?

var i = 0;
(function a(timeout, startTime) {
  console.log(i++);
  if (Date.now() - startTime > timeout) return;
  setTimeout(function() {
    /* window.moveBy(0, x);
    window.moveBy(x, 0);
    window.moveBy(0, -x);
    window.moveBy(-x, 0); */
    a(timeout, startTime);
  }, 0);
})(1000, Date.now());

Upvotes: 0

ssube
ssube

Reputation: 48267

Since JavaScript is single-threaded (as @Luaan mentioned in the comments), your infinite loop will run infinitely and prevent any timeouts or other events from being executed. The runtime won't even try to preempt your loop (break it in the middle to run other code) and will wait until your main function has returned -- which never happens.

You cannot use a busy wait or other, similar loops in JS: they prevent the browser's UI from responding and will cause any events to be deferred until execution has finished and the script thread is free.

To process your loop correctly in an event-friendly fashion, you can either set it up as a timeout every repetition or an interval, like:

this.nudge = function() {
    var x = 10;
    var loop = setInterval(function() {
      window.moveBy(0,x)
      window.moveBy(x,0)
      window.moveBy(0,-x)
      window.moveBy(-x,0)
    }, 100);

    setTimeout(function() {
      clearInterval(loop);
    }, 1000);
}

This simplifies your code by removing the stopped variable and simply started/clearing a deferred loop when the timeout has expired. You can adjust the timing on either function to change the rate of animation and overall duration.

Upvotes: 11

Related Questions