Leave a loop after 2 seonds

后端 未结 3 1325
醉酒成梦
醉酒成梦 2020-12-12 00:49

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:

3条回答
  •  暖寄归人
    2020-12-12 01:05

    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 completely 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.

提交回复
热议问题