Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does setTimeout or setInterval use thread to fire?

I have been reading this article http://ejohn.org/blog/how-javascript-timers-work/ and how setTimeout and setInterval and other async tasks such as button click confused me a little.

I know that JS is a single threaded, that means, AFAIK, all the callback functions (a.k.a. event handlers) will be queued and executed in order. However, look at the image below that I took from the article, linked above:

enter image description here

Each block represents some work, and - at around 10ms - the timer gets fired. I know that its callback function is put on the queue for later execution, but how come the event can get called while something is being executed already?

Is it because setTimeout() starts using a separate thread to count the time internally and fire its completion event?

Please, note that I am not talking about its callback execution here; rather, I am trying to understand how setTimeout can count the time and fires its completion. I know that its callback will be called not before its given time parameters, but maybe later but this is because its callback is queued to later time when the runtime finds some time to check whether there is anything to execute in the queue.

Similar to this question, how come browsers accepts new click to be registered while - let's say - a loop is working behind the scenes at the moment of user click?

If you say browsers maintain different threads for different things, then can we call JS in browsers single threaded?

like image 577
Tarik Avatar asked Feb 21 '15 20:02

Tarik


2 Answers

JavaScript is single threaded, which means that two pieces of JavaScript will not execute at the same time (unless using a worker, but each worker is also single-threaded). But JavaScript isn't the only thing at play when it comes to the environment's API's. Functions like setTimeout, setInterval and addEventListener are implemented natively (or, at-least, outside of the single-threaded JavaScript), and their callbacks are triggered by the environment, such as a browser. It is the environment that puts these callbacks onto the queue, to be executed by the single threaded JavaScript engine. This is how the browser is able to accept new click events to be fired, even though it is still executing some other JavaScript code. This is the reason JavaScript is considered event-driven.

like image 57
Alexander O'Mara Avatar answered Sep 20 '22 07:09

Alexander O'Mara


There is no need to have other threads to explain this behavior. When a timer record is added into the queue, it simply sits there. If the event loop gets control again, it simply checks whether there is a scheduled task whose time is up or not.

There is also no need for an additional thread to keep the global time since this is already delivered by the OS or the execution environment.

Take for example this simple PhantomJS script:

function longRunningTask() {
    for(var i = 0; i < 100000; i++) {
        var s = "",
            s2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        for(var j = 0; j < 1000; j++) {
            s += s2;
        }
    }
}

var start = new Date().getTime();
console.log("begin");
setTimeout(function(){
    console.log("end timer 1s " + (new Date().getTime() - start));
}, 1000);

setTimeout(function(){
    console.log("end timer 10s " + (new Date().getTime() - start));
}, 10000);
longRunningTask();
console.log("end longRunningTask " + (new Date().getTime() - start));

setTimeout(function(){
    console.log("EXIT");
    phantom.exit();
}, 11000);

Which produces the following output:

begin
end longRunningTask 5025
end timer 1s 5029
end timer 10s 10001
EXIT

The one second timer only fires when the control is given back to the event loop.

like image 35
Artjom B. Avatar answered Sep 19 '22 07:09

Artjom B.