1

I know JavaScript has macrotasks and microtasks.

And I know setTimeout(()=>{console.log(1)}, 1000) means register the given function to microtask queue after 1000 milli-seconds.

My questions is how does JavaScript insure this?

When setTimeout(funcRef, delay)'s delay expires, will it raise an event or an interruption that JavaScript will handle it immediately?

Where can I get these details?

Lane
  • 387
  • 1
  • 12
  • 6
    JavaScript doesn't. It's the runtime environment. `setTimeout` calls the runtime environment and JavaScript has finished its job. After the timeout, the runtime environment pushes a new task to the end of the event loop. "Event loop" is the keyword for more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop – jabaa Jan 14 '23 at 15:51
  • 4
    Also browsers (or other environments with `setTimeout()`) don't generally guarantee any degree of accuracy. In a browser, timers in un-focused browser tabs are slowed down significantly, for example. – Pointy Jan 14 '23 at 15:53
  • 1
    No, `setTimeout` doesn't use microtasks. Where did you get that from? – Bergi Jan 15 '23 at 20:01
  • "*will it raise an event*" - yes. "*will handle it immediately?*" - no. It queues a task, as you already said yourself. – Bergi Jan 15 '23 at 20:02

1 Answers1

4

When setTimeout(funcRef, delay)'s delay expires, will it raise an event or an interruption that JavaScript will handle it immediately?

Timers in Javascript are purely event driven, not interrupt driven. So, it will NOT interrupt any code that is currently running. Instead, the code that was running will continue until it returns control back to the event loop at which point one part of the event loop is to check if a timer's time has been reached so its callback should be called.

The internal details of how timers work is implementation-specific. The structure (and code) for nodejs are completely public and there have been many articles written about how timers work in the event loop in libuv in nodejs and the libuv code that implements it all is all available to examine. Here's one nodejs article and a nodejs timing example is covered in this other answer.

Because of the single-threaded, event-driven nature of the Javascript implementations in nodejs and browsers, timer callbacks are run on a best-effort basis with no guarantees for timing accuracy. All that is guaranteed is that the timer callback will be called sometime AFTER it's scheduled time. If the interpreter is busy for awhile, the timer might be called quite late. And, as Pointy mentioned, the browser deprioritizes timers in background tabs/windows and timers may be run even later than usual. Interval timers may even skip entire cycles in the browser environment.

Keep in mind that timers are not part of the Javascript/ECMAscript specification. They are a feature offered by the host environment that is not in the language specification. As such, you are not guaranteed that all details of the implementation will be identical in different environments (for example, nodejs vs. browser).

In particular, there are some implementation oddities/differences around setTimeout(fn, 0). It appears that Chrome schedules a setTimeout(fn, 0) before any other timers that are already in the queue (sometimes), even if the other timers are already past their time to fire, but nodejs does not. Ideally, you would not write code that depends upon this level of nuance. See this answer for more discussion of the setTimeout(fn, 0) oddities.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thank you. I also googled and read that nodejs event loop article. I think I almost understood the principle. **Keep in mind that timers are not part of the Javascript/ECMAscript specification. They are a feature offered by the host environment that is not in the language specification.** => OK, I have understood it is implementation depends, I won't write code depends on these features. – Lane Jan 16 '23 at 03:09