2

I wrote a utility function to create an async timeout:

export function asyncTimeout(timeout: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, timeout))
}

I also wrote a unit test in vitest:

test('asyncTimeout', async ()=> {
  const start = Date.now()
  await asyncTimeout(10)
  const end = Date.now()
  expect(end - start).toBeGreaterThanOrEqual(10)
})

Most of the time this test passes. But sometimes it fails:

AssertionError: expected 9 to be greater than or equal to 10

How is that possible? Is it possible that setTimeout fires earlier than the specified time?

5
  • 3
    You cannot rely on those timeout values to be accurate to the millisecond. Other things may be happening on your computer. Commented May 16, 2024 at 16:14
  • 2
    Or Date might not have enough precision try process.hrtime or process.hrtime.bigint Commented May 16, 2024 at 16:41
  • I have tried with process.hrtime.bigint it gave me 15ms delay which is greater than expected 10ms Commented May 16, 2024 at 16:48
  • date precision is the closest lead to me. But this inaccuracy should not be rounded up? @kennarddh Commented May 16, 2024 at 19:28
  • I don't really know but just use process.hrtime if you need millis or nanos precision. Commented May 16, 2024 at 19:38

1 Answer 1

3

The precision of Dates is just not the highest due to some rounding. This causes it to sometimes be considered one millisecond less or more than it is supposed to be.

If you set it to the expected time minus one millisecond (in this case 9) it should pass all the time. Like so: expect(end - start).toBeGreaterThanOrEqual(9)

Alternatively you could use another form of time measurement than comparing Dates, but this workaround should do the trick if precision down to the millisecond is not needed.

If you want the precision performance.now() is your best option. It is much more precise (down to 0.001ms). You can use it like this:

const start = performance.now();
// Your code 
const end = performance.now();
expect(end - start).toBeGreaterThanOrEqual(10);

You can read more about this approach here: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.