Alvaro Martin Garcia
Alvaro Martin Garcia

Reputation: 11

pause in javascript doesn't work in a loop

This is the sleep function:

    function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

This is a function for actualize the textarea content:

    Luminosidad.prototype.prueba = function(num)
{
    document.getElementById("pruebas").value = num; 
}

When i want do it in a loop, i can only see the last value. This is the code:

for (var i = 1; i < 8; i++)
    {
        sleep(this.opcion.velocidad);
        this.prueba(i);
    }

On the textarea, i can only see "7", the last number. It is like don't actualize correcly. Why can it happens? (sleep works correctly)

Upvotes: 1

Views: 57

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074018

Why can it happens?

Because you never give the browser a chance to show the updates you're making, because you're keeping the UI thread busy looping pointlessly.

Busy-waits are essentially never the right answer to basically any situation.

In this case, what you're looking for is either setInterval of a series of setTimeouts:

function Luminosidad() {}
Luminosidad.prototype.prueba = function(num) {
  document.getElementById("pruebas").value = num;
};
Luminosidad.prototype.loop = function(milliseconds) {
  var i = 1;
  var obj = this;

  setTimeout(next, milliseconds);

  function next() {
    obj.prueba(i++);
    if (i < 8) {
      setTimeout(next, milliseconds);
    }
  }
};
var l = new Luminosidad();
l.loop(500);
<input type="text" id="pruebas">

Note: The loop function returns before any updates to the pruebas element. If you have logic that needs to run after all the updates are complete, you'll want to have loop either accept a callback or return a promise.

Since JavaScript doesn't have a standard form of promise yet (they're coming in ES6, so not far away at all), here's an example of having a callback:

// Requires that your browser support ES6 promises!
function Luminosidad() {}
Luminosidad.prototype.prueba = function(num) {
  document.getElementById("pruebas").value = num;
};
Luminosidad.prototype.loop = function(milliseconds, callback) {
  var i = 1;
  var obj = this;

  setTimeout(next, milliseconds);

  function next() {
    obj.prueba(i++);
    if (i < 8) {
      setTimeout(next, milliseconds);
    } else {
      callback();
    }
  }
};
var l = new Luminosidad();
l.loop(500, function() {
  // This runs when everything is done
  document.body.insertAdjacentHTML(
    "beforeend",
    "All done"
  );
});
<input type="text" id="pruebas">

In ES6, you might use a promise instead:

// Requires that your browser support ES6 promises!
function Luminosidad() {}
Luminosidad.prototype.prueba = function(num) {
  document.getElementById("pruebas").value = num;
};
Luminosidad.prototype.loop = function(milliseconds) {
  var obj = this;
  return new Promise(function(resolve) {
    var i = 1;

    setTimeout(next, milliseconds);

    function next() {
      obj.prueba(i++);
      if (i < 8) {
        setTimeout(next, milliseconds);
      } else {
        resolve();
      }
    }
  });
};
var l = new Luminosidad();
l.loop(500).then(function() {
  // This runs when everything is done
  document.body.insertAdjacentHTML(
    "beforeend",
    "All done"
  );
});
<input type="text" id="pruebas">

Upvotes: 5

Related Questions