Why doesn't Javascript have a concept of timers?

Every once in a while, I hear about how setTimeout, setInterval, etc are not native to Javascript, but are functions that browsers and node choose to implement on top of Javascript. Javascript doesn't have the concept of timers and delays.

Is there any particular reason for this? Or is that just how things are currently in the spec, but it could change in the future?

1 Like

There is an ideological reason for it (TL;DR: timers are a runtime-specific concept and not very well suited for a general-purpose embedded engine with minimal awareness of its surrounding execution environment), but I'll defer to someone on TC39 to provide more complete background.

Just for full disclosure, I disagree with them on the specific point of timers, but agree with the rest and have even gone as far as to push for moving the legacy HTML string methods to the WHATWG spec.

1 Like

The 2 reasons I’ve heard are

  • to limit ability to perform a timing attack
  • so JS can be used in a pure compute-only context e.g css worklets
1 Like

so JS can be used in a pure compute-only context e.g css worklets

Does this mean JavaScript can't natively support any async task creation? (well, beyond waiting for a micro-task when you use await on a non-promise). I.e. it would never be able to support the fetch() API natively?

I know there's other reasons why fetch() can't be supported, like, not all engines are in an environment where they want you to be able to do network requests. But, would this be one of the reasons against nativly supporting such a feature? So you can't make a CSS worklet await on something that may take an arbitrary amount of time?

Yes.

(there are many reasons why fetch is impossible to support outside of a browser environment - in particular, its tight coupling to the concept of URLs and cookies etc)

1 Like

Yes. But even if it did, what would your async task do? JavaScript doesn't natively support any input/output routines, so there's no point in writing or executing a "native JavaScript" program in the first place.
Leaving all this mess of interacting with the outside world to the host environment is a good idea imo. Prior to the job queues introduced with ES6, JS didn't even have a model of the event loop; and prior to the introduction of shared memory there was no threading model either.

No wonder I was struggling so much with coming up with a good example of an async task creation besides timeouts for JavaScript, because there aren't any good examples. It makes sense that native JavaScript doesn't support any sort of I/O.