1

I have a chess program that searches moves using a recursive alphaBeta algorithm (and some layers on top of that). I want to stop searching after 10 seconds (but I try with 1 second while making it work), so I use setTimeout to set a global flag.

  let timeOut = false;
  let i = 0;

  setTimeout(() => {
    timeOut = true;
    console.log('timeout');
    console.log('timeout');
    console.log('timeout');
    console.log('timeout');
  }, 1000);

  while (i < 1000 && timeOut === false) {
    score = mtdf(pos, i, score)
    console.log('depth:' + i + ', size: ' + tp.size());
    i++;
  }

This sure runs in the browser so I know the console.log statements should be printed in the browser but they aren't. The callback isn't called. Help please.

Edit: Added timeOut variable initialisation to make it more clear. Also, sorry, forgot to add i initialization (not that these declarations are even relevant to the question, since the problem is that setTimeout callback isn't even being executed...)

Mattias
  • 715
  • 1
  • 6
  • 19

3 Answers3

3

setTimeout will run the function you pass to it:

  • After the specified time has passed
  • After the minimum time for a timeout has passed
  • When the event loop isn't busy doing something else

… whichever is the latest.

You can't use a timeout to interrupt your while loop. The JavaScript engine is too busy running the while loop to check to see if there are any functions waiting to run on the timeout queue.

Your function will be called after the loop has finished when the JS engine is no longer busy.


Don't try to interrupt your loop from the outside.

Before you enter the while loop, record the current time.

Each time you go around the loop, compare the current time with the recorded time.

If the difference is greater than the period you want to allow the loop to run from, exit the loop

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • This is correct I think. This question confirms it: https://stackoverflow.com/questions/14863022/settimeout-behaviour-with-blocking-code – Mattias Aug 08 '18 at 08:01
1

Javascript is single threaded meaning that execution of "asynchronous" statements like setTimeout, setInterval, and XMLHttpRequest get queued on a single thread. If something blocks the thread (like your heavy while() loop) async statements get delayed.

See here for more elaborate answer

To make your code work, I suggest looking at the timestamp

var t0 = new Date().getTime(), t1 = t0;
while(true)
{
    // do stuff here
    t1 = new Date().getTime();
    if (t1 % 100 === 0) console.log(t1); // [debug ]print something every 100ms
    if (t1 - t0 > 1000) break; // kill the loop after one second

}
Eriks Klotins
  • 4,042
  • 1
  • 12
  • 26
-1

setTimeout is asynchronous meaning the program won't wait for the setTimeout to finish and the code will continue executing.

You need to use Promise to wait for the setTimout to finish so your code will behave properly.

Also, the problem of your code also lies in the variable declarations, you didn't declare the i and timeOut variables.

let timeOut = false;

new Promise((resolve) => {

  setTimeout(() => {
    timeOut = true;
    console.log('timeout');
    console.log('timeout');
    console.log('timeout');
    console.log('timeout');
    resolve();
  }, 1000);

}).then(() => {

  let i = 0;
  while (i < 1000 && timeOut === false) {
    score = mtdf(pos, i, score)
    console.log('depth:' + i + ', size: ' + tp.size());
    i++;
  }

});
Julian Paolo Dayag
  • 3,562
  • 3
  • 20
  • 32
  • 1
    You've misunderstood the question. The OP is trying to stop the while loop from running for more than a second. They aren't trying to delay its start by a second. – Quentin Aug 08 '18 at 07:50
  • Yeah, I got that. So I already mentioned at the last paragraph that the problem lies in the variables. – Julian Paolo Dayag Aug 08 '18 at 07:50
  • "Yeah, I got that" — So what is that promise stuff all about then. – Quentin Aug 08 '18 at 07:51
  • because he uses the `timeOut` in his loop while the `timeOut` variable assignment is used inside the `setTimeout`. His code isn't semantically correct. What's the condition `timeOut === false` for when it will always be false at the end? better just remove it from the condition. Unless, there's something he wants to do with the `timeOut` variable inside his loop that we don't know thus the reason why he should wrap it with a promise. – Julian Paolo Dayag Aug 08 '18 at 07:52
  • They want the loop to start. Then they wants the timeout to run, setting `timeOut` to `false`. Then they want the loop to stop because `timeOut` is `false`. That can't happen at all, and delaying the start of the loop until the timeout function has been executed and set `timeOut` to `false` won't achieve it. – Quentin Aug 08 '18 at 07:59