0

I'm trying to run some synchronous function which should wait for a certain time and then return control. But for some reason, it keeps executing asynchronously, or at least that's how it looks.

This is the code:

function pause(ms) {
  var dt = new Date();
  while (new Date() - dt <= ms) {
    /* Do nothing */
  }
}

console.log("start calculation..");
pause(3000);
console.log("calculation finished!");

this immediately shows the following in the console:

start calculation..
calculation finished!

There is no delay at all, as if the pause function is executed asynchronously.

I've tried 3 different versions of the pause function, it doesn't make any difference.

You can see this in the sandbox I put the code in.
(you must go to preferences - sandbox.config.json and turn of "Infinite loop protection" for it to work)

  1. Why isn't the code running synchronously, first showing the "start calculation..." message, and then the second message after a 3 second delay?
  2. Is there a better way to simulate running a time-expensive synchronous function?
  • 3
    Looks like the `while` loop prevents the browser from "flushing" the messages to the console. If you just run this code in your console you will still see the messages appearing at the same time but *after* 3 seconds (at least that happens in Firefox). – Felix Kling Nov 30 '21 at 17:46
  • 1
    The compiler might optimize away empty loops. – daniu Nov 30 '21 at 17:47
  • 1
    *"Is there a better way to simulate running an expensive synchronous function?"* I think you need to provide more context here. The code does exactly what you want it to do, it's just that something outside the realm of the JavaScript engine (the browser console) doesn't get updated in real time. So what is it exactly that you want to achieve? (not to mention that long running synchronous operations should be avoided anyway) – Felix Kling Nov 30 '21 at 17:56
  • @FelixKling I meant a time-expensive synchronous function. I'm just trying to mock a (synchronous) function which takes some time to run. – Ruben Lemiengre Nov 30 '21 at 18:06
  • Then what you have will do that, despite the timing of the console output. As mentioned maybe the compiler will remove empty loops so making the function compute something might be "safer". – Felix Kling Nov 30 '21 at 18:11
  • You can make it work by getting time from an Date object: `var dt = new Date().getTime();` – Narek Ghazaryan Dec 05 '21 at 21:37
  • @NarekGhazaryan That seems to do the exact same thing – Ruben Lemiengre Dec 06 '21 at 22:58

1 Answers1

0

Since my question has only been partially answered, I will provide the solution myself, in case other people have similar issues:

First of all, this code now works as intended in the console of Chrome, Chromium and Firefox. It didn't before, so perhaps there's been an upgrade to the javascript engine in this regard. When running the code in the provided CodeSandbox though, it still logs the two lines simultaneously, after a 3 seconds delay.

As people have pointed out, 2 things could possibly be the cause of this:

  • the compiler removing empty loops
  • the console messages not refreshing as long as the loop is running

This code will fix both issues:

function pause(ms, start=new Date()) {
  while (new Date() - start <= ms) {
    setTimeout(()=>pause(ms,start))
  }
}

console.log("start calculation..");
pause(3000);
console.log("calculation finished!");

Calling a SetTimeout (even with a 0 ms delay) will cause the rest of the code execution (a recursive function call) to be thrown back on the event loop for later processing, after allowing for the execution of event callbacks first. This ensures other events - such as logging of the console - will not be blocked.

It also puts some actual code inside the loop, so that the loop will not be removed by any compiler code optimisation.