0

I am trying to make a timeout function that throws an error in case a function hangs for too long.

I have the following code:

function go() {

  try{
    console.log('started, timeout in 2 seconds...');
    setTimeout(()=>{
      throw new Error('Timed Out!');
    }, 2000);

    while(true){
      //will run forever
    }
  }catch (e) {
    console.log('timeout function worked!');
  }
}

go();

However, the error is never thrown. I think this is because of how the event loop works in JS, but I'd like for my timeout function to execute after 2 seconds regardless of what else is happening. How do I achieve this?

B Sweeze
  • 3
  • 1
  • This will only work if you can split the work up, or move it into a worker thread, so the browser has time to do something else - like executing the queued `setTimeout` call – Andreas Feb 14 '19 at 19:19
  • [Javascript - how to avoid blocking the browser while doing heavy work?](https://stackoverflow.com/questions/10180391/javascript-how-to-avoid-blocking-the-browser-while-doing-heavy-work) – Andreas Feb 14 '19 at 19:21

4 Answers4

0

I'd like for my timeout function to execute after 2 seconds regardless of what else is happening. How do I achieve this?

You can't really. As you suspected, the issue is related to the event loop. There's only one thread at your disposal, and you've put it into an infinite loop. Since you never return, the event loop doesn't have a chance to run the function specified by the setTimeout.

If you want your while loop to stop, your while loop needs to be the one to stop it. Perhaps something like this:

const before = Date.now();
while (true) {
  // do stuff
  if (Date.now() - before > 2000) {
    throw new Error('Timed Out!');
  }
}
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • In my real application the function is hanging on an http: request, rather than a while loop like in this situation. In my real application would it be possible to force the execution? I'm still fairly new to JS but it seems http requests are handled differently than the regular event loop. Thank you very much for your help! – B Sweeze Feb 14 '19 at 19:26
  • Unless you're using a synchronous http request (which you shouldn't), it does not block the thread. The timeout will go off after approximately 2 seconds, assuming nothing is hanging the thread at that time. – Nicholas Tower Feb 14 '19 at 20:02
  • You'll probably want to ask a new question with your real scenario. We gave answers for the one you posted, which doesn't seem to be relevant to your actual case. – Nicholas Tower Feb 14 '19 at 20:03
0

I think this is because you enter inside the infinite loop first and never get out so your settimeout will never fire.

I don't know what your are try to achieve but if you want to throw error, move the while loop inside the settimeout at the end. By the way that make no sense

Amadou Beye
  • 2,538
  • 3
  • 16
  • 37
0

setTimeout() doesnot work as you think. Until the while loop is running. The setTimeout() function will not be called.

Javascript doesnot support multithreading because it is an interpreted language. Multithreading: is a type of execution model that allows multiple threads to exist.See more

Below is the example.

function loop(){
  console.time('time');
  for(let i = 0;i<10000000;i++){
    if(i % 2000000 === 0) console.log("I am looping");
  }
  console.timeEnd('time');
  console.log("Loop finished");
}
loop();
setTimeout(() => {
  console.log("I am logged from setTimeout")
},0)
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
0

You can't do anything if the event loop can't proceed. But, the below code should be closer to what you are looking for. If you need to do a while statement, do the code further down.

function go() {
  try{
    var timeout = setTimeout(()=>{
      throw new Error('Timed Out!');
    }, 2000);

    //do stuff; it can't hog the event loop
  }catch(e){
    
  }
  clearTimeout(timeout);
  return true; //return value
}

go();
var iterations = 0;
while(condition && iterations < 10){
  //do stuff
  iterations++;
}
David Kirk
  • 342
  • 3
  • 5
  • @NicholasTower has a better while statement, but it seems you (@BSweeze) haven't asked the question you need to ask. – David Kirk Feb 14 '19 at 19:59