- Event loop
- Run to completion
- The ongoing journey: Async strategies
- The road ahead: Streams
- Observer pattern
- (Functional) Reactive Programming
This is the event loop, which is single-threaded by nature.
Where does the asynchrony come from then? Well, this engine doesn’t run in isolation. It runs inside a hosting environment, which is for most developers the typical web browser, or other types of devices or environments, like a server, through Node.js.
So, when you make an AJAX request to fetch some data from a server, you set up the “response” code in a function (commonly called a “callback”), and the JS engine tells its intention to the hosting environment. Then, the browser, or hosting environment, waits for the response from the network, and when it has something to give you, it schedules the callback function to be executed by inserting it into the event loop.
Concurrency is when two or more chains of events interleave over time, such that from a high-level perspective, they appear to be running simultaneously (even though at any given moment only one event is being processed).
In traditional parallelism, processes and threads execute independently and may execute simultaneously, on separate processors, or even separate computers, but multiple threads can share the memory of a single process.
Threaded programming is very tricky, because if you don’t take special care to prevent this interleaving and associated shared memory problems, you can get very surprising, nondeterministic behavior that frequently leads to headaches.
SharedArrayBuffer, which are a recently added special use case).
Run to completion
x() starts running, the entirety of its code will finish before any of the code in
y() can run, or vice versa. This is called “run-to-completion” behavior.
At any given moment, only one event can be processed from the queue at a time. While an event is executing, it can directly or indirectly cause one or more subsequent events.
So we still have nondeterminism. But it’s at the function (event) ordering level, rather than at the statement ordering level, as it is with threads. In other words, there is somehow more determinism than with threads, but it’s not avoided, so we have to be careful about this.
In the second part of this article series, we’ll continue to the next phase of our journey: async strategies. You can read it here.