admin管理员组

文章数量:1310508

I would like to repeat a text for 2 seconds in a while loop. How do I break the loop after 2 seconds?

This is what I have tried so far but it doesn't work:

var repeat = true;
setTimeout(function() { var repeat = false }, 2000)
while(repeat) {
    console.log("Let's repeat for 2 seconds...");
}

I would like to repeat a text for 2 seconds in a while loop. How do I break the loop after 2 seconds?

This is what I have tried so far but it doesn't work:

var repeat = true;
setTimeout(function() { var repeat = false }, 2000)
while(repeat) {
    console.log("Let's repeat for 2 seconds...");
}
Share Improve this question asked Mar 22, 2018 at 22:56 Reza SaadatiReza Saadati 5,4394 gold badges33 silver badges69 bronze badges 6
  • 4 Not possible with the timeout, the while loop locks it up. You would need to check the time inside the loop. Still not great because it will still lock up the browser and the browser can stop it – epascarello Commented Mar 22, 2018 at 22:59
  • 2 Possible duplicate of Using javascript how to break the while loop after a set time? – Smokey Dawson Commented Mar 22, 2018 at 23:02
  • 1 Um, that dupe is a very bad one ?! – Jonas Wilms Commented Mar 22, 2018 at 23:21
  • 2 @ivar please undelete your answer, its a good one – Jonas Wilms Commented Mar 22, 2018 at 23:21
  • @JonasW. Well, at least this one got some good answers. Maybe we should consider closing the other as a dupe of this :p – merv Commented Mar 22, 2018 at 23:36
 |  Show 1 more ment

3 Answers 3

Reset to default 8

Additionaly to the other answer you could just check the time instead:

 const start = +new Date;

  while(+new Date < start + 2000) {
     console.log("Let's repeat for 2 seconds...");
 }

JavaScript is single threaded. This means that as long as your loop runs, your timeout will never be fired.

Depending on what you want and whether or not you want to lock down your browser (by using an actual infinite loop), you can use the setInterval as a loop, and use the setTimeout to stop the interval after 2 seconds.

console.log("Starting loop");

var interval = setInterval(function () {
    console.log("Let's repeat for 2 seconds...");
}, 0);

setTimeout(function() {
    clearInterval(interval);
    console.log("Finished loop");
}, 2000);

If you're concerned at all with performance of this loop, the proposed solution would be a problem.

Note that in most cases, you shouldn't be synchronously iterating a huge number of times in Javascript since that would pletely block the browser or server during this time, but there are some cases where this might be needed. Just be aware that this is generally not a good thing to do.

What follows is my own experimentation with several options to reduce the overhead of checking a timeout, since I was using it to benchmark other code.

I added console.time logs to both solutions, and added a couple of optimizations that might be worth considering.

The accepted solution has the worst performance:

const label = 'interval';
console.time(label);
let i = 0;
const interval = setInterval(
  () => {
    i += 1;
  },
  0);

setTimeout(
  () => {
    clearInterval(interval);
    console.timeEnd(label)
    console.log(`${i.toExponential()} iterations`);
  },
  2000);
// interval: 2001.100ms
// 4.93e+2 iterations

The next answer has much better performance, but it's still performing unnecessary work, type conversions and addition on every loop run:

let i = 0;
let start = +new Date;
let label = '+new Date + 2000';
console.time(label);
while ((+new Date) < start + 2000) {
  i += 1;
}

console.timeEnd(label)
console.log(`${i.toExponential()} iterations`);
// +new Date + 2000: 1999.800ms
// 1.0921121e+7 iterations

By using Date.now() instead of (+new Date) you get a performance increment of around 2.5x:

let label = 'Date.now()';
console.time(label);
let end = Date.now() + 2000;
let i = 0;
while (Date.now() < end) {
  i += 1;
}
console.timeEnd(label)
console.log(`${i.toExponential()} iterations`);
// Date.now(): 1999.000ms
// 2.6477108e+7 iterations

If performance is much more important that the exact nanosecond when you stop, and the operations are super fast, you can reduce the number of checks for even more operations:

let label = 'fuzzy + 2000';
console.time(label);
let end = Date.now() + 2000;
let i = 0;
// Only check the timeout every 1000 operations thanks to lazy evaluation.
while (i % 1000 !== 0 || Date.now() < end) {
  i += 1;
}
console.timeEnd(label)
console.log(`${i.toExponential()} iterations`);
// fuzzy + 2000: 1999.800ms
// 6.5632e+8 iterations

30x better! You will need to tweak the frequency of the checks based on both the average loop time and how exact you want your timeout to be.

本文标签: javascriptLeave a loop after 2 seondsStack Overflow