简体   繁体   中英

How does setInterval and setTimeout work?

I was in an awkward situation ,

I am working with pure JavaScript for almost 3 years, and I know that JavaScript is single-threaded language, and that you can simulate asynchronous execution using setInterval and setTimeout functions,

but when I thought about how they can work I couldn't clearly understand it. So how these functions affect execution context?

I suppose that in specific time runs only one part of the code and after it switches to another part. If so, then would a lot of setInterval or setTimeout calls affect performance?

Javascript is singled-threaded but the browser is not. The browser has at least three threads: Javascript engine thread, UI thread, and timing thread, where the timing of setTimeout and setInterval are done by the timing thread.

When calling setTimeout or setInterval , a timer thread in the browser starts counting down and when time up puts the callback function in javascript thread's execution stack. The callback function is not executed before other functions above it in the stack finishes. So if there are other time-consuming functions being executed when time up, the callback of setTimeout will not finish in time.

How setTimeout / setInterval work's in JavaScript

Browser has API for Timer function just like API for event ex.

'click'

'scroll'

Assume that you have following code in your application

function listener(){
    ...
}

setTimeout(listener, 300)

function foo(){
    for(var i = 0; i < 10000; i++){
        console.log(i)
    }
}

foo()

看看函数执行是如何在 javascript 中工作的

At this point as per our code we wrote above our call stack will look like

Call Stack -> foo

And let's assume that foo will take 1s to complete it's execution, as we already defined 1 timeout in our code and we are running it before "foo" complete's it's execution ie at 300ms

What will happen then ?

Does javascript stop executing foo and start executing setTimeout ?

No

As we already know javascript is single threaded so it has to complete execution of foo before moving ahead, but how does browser insure that after execution of foo the "setTimeout" will execute ?

Here javascript magic comes into picture

When 300ms is expired the browser "Timer API" kicks in and put the timeout handler into "Message Queue"

At this point "Message Queue" in above image will look like

Message Queue -> setTimout:listner

And

Call Stack -> foo

And when "Call Stack" becomes empty ie foo completes it's execution the "Event Loop" as shown in the image will take the message from message queue and push it into stack

The only job of "Event Loop" is when "Call Stack" becomes empty and "Message Queue" has entry in it then dequeue the message form "Message Queue" and push it into "Call Stack"

At this point Message Queue in above image will look like

Message Queue ->

And

Call Stack -> listener

And that's how setTimeout and setInterval works, even though we specify 300 ms in the setTimeout it will execute after "foo" completes it's execution in this case ie after 1s. And that's why timer specified in setTimeout/setInterval indicates "Minimum Time" delay for execution of function.

Javascript is single threaded but browser is not.

There is 1 stack where function and statements get executed. there is 1 queue where function are queued to be executed. there are web APIs which can hold the function for particular time, defined in setTimeout and setInterval in event table.

when javascript engine execute js file line by line, if it finds a line as statement or function call it load it on stack and execute but if it is setTimeout or setInterval call, then function handler associated with setTimeout or setInterval is taken out by TIME API (one of web API of browser)and hold it for that time.

Once this time is over, Time Api put that function at end of execution queue.

Now Execution of that function depends on other functions calls which are ahead of in queue.

Note: this function call is called upon window object.

setTimeout(function () {console.log(this)}, 300)

Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

JavaScript is a single-threaded scripting language, so it can execute one piece of code at a time (due to its single-threaded nature) each of these blocks of code is “blocking” the progress of other asynchronous events. This means that when an asynchronous event occurs (like a mouse click, a timer firing, or an XMLHttpRequest completing) it gets queued up to be executed later.

setTimeout() when you use setTimeout() it will execute only when its turn comes in a queue, if an earlier event (of setTimeout) blocks due to some reason setTimeout can be delayed than the specified time in setTimeout() function. during the execution of setTimeout callback function, if any event occurs(eg click event),it gets queued up to be executed later.

setTimeout(function(){
  /* Some long block of code... */
  setTimeout(arguments.callee, 10);
}, 10);

setInterval(function(){
  /* Some long block of code... */
}, 10);

setInterval()

  • Similar to setTimeout but continually calls the function (with a delay every time) until it is canceled.

  • setTimeout code will always have at least a 10ms delay after the
    previous callback execution (it may end up being more, but never less) whereas the setInterval will attempt to execute a callback every 10ms regardless of when the last callback was executed.

  • If a timer is blocked from immediately executing it will be delayed
    until the next possible point of execution (which will be longer than the desired delay). Intervals may execute back-to-back with no delay if they take long enough to execute (longer than the specified
    delay).

Just a note in regards to my experience, If you are going to use setTimeout(), the function will always be delayed (and I mean executed later) or executed after further code which is not 'timeouted'. This may happen even with functions which have delay = 0 and is caused by Event Loop.

See example below:

setTimeout(function() {
    console.log('Second');
}, 0)

console.log('First');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM