0

Is there a way to pause code execution for just 1ms? The best I can do right now is around 5ms I'm making a sorting visualizer to practice. I started with using divs to represent values of the array that's being sorted but it seemed slow on large arrays so I switched to canvas. But now my choke point is this function I am using to pause the code for just a bit so that the changes on the array are actually visable, otherwise it is so fast that it just sorts at button click. Below is what I used to test the pause function (which I am using in my visualizer), to see if it is actually 1ms because it didn't feel like it.

const number = 100
const delay = 1

const pause = () => new Promise((res) => setTimeout(res, delay));

async function testPause() {
  for (let i = 0; i < number; i++){
    console.time("pause")
    await pause()
    console.timeEnd("pause")
  }
}

testPause()

It works ok for delay >= 4 . The console displays values of 4 +- 0.5ms. But below 4 it displays same values as for 4. Even when delay = 0. Is there a better way to do this?

  • 1
    `setTimeout` has a minimum delay time of 4ms. What you should probably look into is `requestAnimationFrame` if you want to do visualisation with lower latency. – VLAZ Jun 28 '21 at 21:43
  • Since this is for animation purposes, you could also speed it up by making it so the pause only happens every other call to pase(), or every third call, etc. – Scotty Jamison Jun 28 '21 at 21:49
  • Instead of relying on `setTimeout`, try exploring using `requestAnimationFrame`, and compare the ms elapsed from one frame to another. – Terry Jun 28 '21 at 21:51
  • 1
    `requestAnimationFrame` minimum is 16ms isn't it? that's greater than 4 :p – Jaromanda X Jun 28 '21 at 22:21
  • @VLAZ note that the 4ms limitation is only when the timeout has been called through 5 levels of nesting, before that, it's now 0 in Chrome and Firefox, and 1ms in node (used to also be 1ms in Chrome). rAF will fire at screen refresh rate, so unless you have a 250Hz+ monitor at hand (they're still quite rare), that will probably be more than 4ms. – Kaiido Jun 29 '21 at 03:15
  • Might also be of interest for you: https://stackoverflow.com/questions/54478195/how-to-allow-web-workers-to-receive-new-data-while-it-still-performing-computati/54481612#54481612 – Kaiido Jun 29 '21 at 03:18

1 Answers1

0

Since your end-goal is to create an animation, you can simply just call your "nextAnimationStep" function two or three times as often. The end-user shouldn't notice any stutter from this, due to the fact that the framerate should be high enough to keep it looking smooth.

Here's an example where an animation is running too slow:

const squareEl = document.getElementById('square')
let x = 0

function runNextAnimationStep() {
  squareEl.style.left = x++ + 'px'
  return x > 150
}

async function step() {
  const complete = runNextAnimationStep()
  if (!complete) {
    requestAnimationFrame(step)
  }
}
step()
#square {
  width: 32px;
  height: 32px;
  background: blue;
  position: absolute;
}
<div id="square"></div>

And here's how we sped it up, without modifying runNextAnimationStep():

const squareEl = document.getElementById('square')
let x = 0

function runNextAnimationStep() {
  squareEl.style.left = x++ + 'px'
  return x > 150
}

async function step() {
  let complete = false
  for (let i = 0; i < 3 && !complete; ++i) {
    complete = runNextAnimationStep()
  }
  if (!complete) {
    requestAnimationFrame(step)
  }
}
step()
#square {
  width: 32px;
  height: 32px;
  background: blue;
  position: absolute;
}
<div id="square"></div>

Note that the above brute-force solution will provide different animation speeds depending on how quickly requestAnimationFrame() fires. To make it run more consistently, you'll need to decide on your desired framerate, and use the DOMHighResolutionTimestamp that requestAnimationFrame() provides to the callback, to automatically adjust how often you call your runNextAnimationStep() function, so that on average, it'll call that function the same number of times per second.

Scotty Jamison
  • 10,498
  • 2
  • 24
  • 30