-1

I am using the following code to see if the JavaScript execution gets blocked while a synchronous function gets into a long loop.

function delayBySeconds(sec){
  let start = now = Date.now();
  while((now - start) < (sec * 1000)){
    //console.log(now);
    now = Date.now();
  }
}

const seconds = 20;
delayBySeconds(seconds);
console.log(`${seconds} seconds passed`);

It prints the message immediately which shows the execution doesn't wait for the called function to complete its loop. How does that work? I mean if the delayBySeconds function works properly, how does the message get printed immediately? It's only experimental, of course, it doesn't make sense I would use it for some practical delay.

Hamid Ali
  • 29
  • 4

2 Answers2

0

It's a synchronous code execution. The console is waiting until the function is not executed fully. You are not seeing any delay because you are not performing any task inside the loop.

You can see the delay if you uncomment the console inside the while loop.

sawan nirala
  • 181
  • 1
  • 4
  • How is an assignment statement ( now = Date.now() ) not performing a task? Even a while(1); is performing a task. I found what the actual problem was, though. Actaully, I was trying this code on https://jsbin.com/ online editor. When I tried it in a standalone browser on my own PC, it worked. It is blocking the execution for as many seconds as specified. So a lesson is that if any piece of JS code executes unexpectedly, check it is a standalone browser. – Hamid Ali Oct 07 '20 at 04:45
  • Yes, you are right. jsbin console is different from browser console. If you tried it in browser console, It will halt the execution. – sawan nirala Oct 07 '20 at 04:52
0

Because of the fact that JavaScript is always synchronous and single-threaded, it does not wait for your function execution to finish before moving on to next statement. Therefore, to properly wait for a function to finish execution, we used Promise/Then sort-of "framework" to make asynchronous call to function, i.e. waiting for it to complete before moving on. Now after ES2017, we can use async/await to kinda simplify the process.

Snippet using Promise

const delayBySeconds = sec => new Promise(resolve => {
  let start = now = Date.now();
  while((now - start) < (sec * 1000)){
    // console.log(now - start);
    now = Date.now();
  }
  resolve()
})

const seconds = 10;
delayBySeconds(seconds).then(()=>
console.log(`${seconds} seconds passed`))

snippet using async/await

const delayBySeconds = async sec => {
  let start = now = Date.now();
  while((now - start) < (sec * 1000)){
    // console.log(now - start);
    now = Date.now();
  }
  return
}

const main = async () => {
  const seconds = 7;
  await delayBySeconds(seconds)
  console.log(`${seconds} seconds passed`)
}

main()

Notice that async/await can only be used in an async function, so you have to wrap it up in a function if you are using native js. However, some, like Deno, a fairly recent backend js framework, has global support for async/await so you don't have to wrap it up in there.

Burning Alcohol
  • 1,839
  • 1
  • 5
  • 20
  • And also, I won't criticize the code because this is your experiment only, but notice that a while loop like this wastes quite a lot of computing resources as it checks if a second passes for hundreds of times in every second. Refer to [link](https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep) for better `sleep` alternative – Burning Alcohol Oct 07 '20 at 04:37
  • Yes, I understand it is not a practical code. Please refer to my reply to the previous answer by Sawan Nirala – Hamid Ali Oct 07 '20 at 04:51
  • Hope that helped, maybe you can mark my answer as accepted if that helped, thanks! – Burning Alcohol Oct 07 '20 at 04:56