Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript internals - clearTimeout just before it fires

Let's say I do this:

var timer = setTimeout(function() {
    console.log("will this happen?");
}, 5000);

And then after just less than 5 seconds, another callback (from a network event in NodeJS for example) fires and clears it:

clearTimeout(timer);

Is there any possibility that the callback from the setTimeout call is already in the queue to be executed at this point, and if so will the clearTimeout be in time to stop it?

To clarify, I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it, but the other callback is currently running so the message is added to the queue. It seems like one of those race condition type things that would be easy to not account for.

like image 777
Gus Avatar asked Jun 10 '14 09:06

Gus


People also ask

What does clearTimeout do in JavaScript?

The global clearTimeout() method cancels a timeout previously established by calling setTimeout() .

Can we clearTimeout inside setTimeout?

clearTimeout() inside setTimeout() method not working in JS It does "work", but your logic is incorrect. After you called clearTimeout you are calling setTimeout again. Instead of calling clearTimeout you should just exit the function.

Does clearTimeout stop execution?

Methods setTimeout(func, delay, ... args) and setInterval(func, delay, ... args) allow us to run the func once/regularly after delay milliseconds. To cancel the execution, we should call clearTimeout/clearInterval with the value returned by setTimeout/setInterval .

Is clearTimeout necessary?

You don't actually need to use clearTimeout , you only use it if you wish to cancel the timeout you already set before it happens. It's usually more practical to use clearInterval with setInterval because setInterval usually runs indefinitely.

What does cleartimeout do in JavaScript?

clearTimeout() The clearTimeout() function in javascript clears the timeout which has been set by setTimeout()function before that. setTimeout() function takes two parameters. First a function to be executed and second after how much time (in ms).

How do I stop a setTimeout () function in JavaScript?

The ID value returned by setTimeout() is used as the parameter for the clearTimeout() method. myVar = setTimeout("javascript function", milliseconds); Then, if the function has not already been executed, you will be able to stop the execution by calling the clearTimeout() method.

How do I clear a timer set in JavaScript?

The clearTimeout () method clears a timer set with the setTimeout () method. The ID value returned by setTimeout () is used as the parameter for the clearTimeout () method. Then, if the function has not already been executed, you will be able to stop the execution by calling the clearTimeout () method.

How to clear the timeout of a window in Java?

The clearTimeout () method is a part of WindowOrWorkerGlobalScope class. The timeoutID parameter is an identifier that signifies the timeout () function which you would want to clear. This will be the ID that was returned by the setTimeout () function. You can clear the timeout by using this id which identifies the timeout.


2 Answers

Even though Node is single thread, the race condition the question describes is possible.

It can happen because timers are triggered by native code (in lib_uv). On top of that, Node groups timers with the same timeout value. As a result, if you schedule two timers with the same timeout within the same ms, they will be added to the event queue at once.

But rest assured node internally solves that for you. Quoting code from node 0.12.0:

timer.js > clearTimeout

exports.clearTimeout = function(timer) {
  if (timer && (timer[kOnTimeout] || timer._onTimeout)) {
    timer[kOnTimeout] = timer._onTimeout = null;
    // ...
  }
}

On clearing a timeout, Node internally removes the reference to the callback function. So even if the race condition happens, it can do no harm, because those timers will be skipped:

listOnTimeout

if (!first._onTimeout) continue;
like image 149
Sitegui Avatar answered Oct 23 '22 22:10

Sitegui


Node.js executes in a single thread.

So there cannot be any race conditions and you can reliably cancel the timeout before it triggers.

See also a related discussion (in browsers).

I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it

Without having looked at Node.js internals, I don't think this is possible. Everything is single-threaded, so the interpreter cannot be "in the process" of doing anything while your code is running.

Your code has to return control before the timeout can be triggered. If you put an infinite loop in your code, the whole system hangs. This is all "cooperative multitasking".

like image 5
Thilo Avatar answered Oct 23 '22 21:10

Thilo