When javascript runtime finds setTimeout() method, it sends it to Event table. How does runtime know that setTimeout() is a WEB API? Does it first look for setTimeout() method in the current context and then if not found assumes it as a WEB API?
When javascript runtime finds setTimeout() method, it sends it to Event table.
JavaScript doesn't "know" or care what setTimeout does. :-) It's just that setTimeout is one of the functions defined in the host environment provided to the JavaScript engine by the host (the browser, in your example). When you use JavaScript to call the function, the function's implementation (provided by the host environment) is executed with the information you provide. It's the host, not the JavaScript engine, that knows what to do with the arguments you provide to setTimeout.
When the host (the browser or Node.js or whatever) needs to create a new runtime environment (for instance, for a window), one of the things it does is create an object to be the host-provided global object for that environment (more properly called a realm), including putting any properties on that object (like setTimeout) that provide host-defined features. It provides that object to the JavaScript engine via what the JavaScript specification calls the InitializeHostDefinedRealm abstract operation. When the JavaScript engine runs your code that uses setTimeout, it sees the identifier setTimeout and looks in the current execution context to see if setTimeout is defined there; if it isn't, the engine looks at the parent execution context, and so on, until it reaches the global execution context, which gets its globals from the host-provided global environment (in part; it also has other globals). So, having found the function matching setTimeout, the JavaScript engine calls that function — which runs the host-defined code for the function, which sets the timer.
So the JavaScript engine doesn't know what setTimeout does, just that there is a setTimeout function on the global object it got from the host.
In terms of identifying which function to run, it doesn't make any difference whether a function is built into the engine, or added at run-time (this fact is really useful, allowing functions to be "polyfilled" if the engine doesn't provide them).
When you write foo(), JS actually looks for a variable with that name (this unification of variables, properties, functions and methods is an unusual feature of JS). It looks for it first in the local scope, then in the parent of that scope, and so on up the "scope chain".
The last place it looks is the "global object", which in a browser is the window object. So if you define window.foo as a function, you can call foo() from anywhere that doesn't have its own function called foo in scope.
Built-in functions work just the same way: when the JS engine starts up, it (conceptually) defines a whole bunch of functions on the window object, with special implementations referring to internal operations in the engine rather than composed of JS code.
So when you call setTimeout, JS walks up the scope chain, and if it doesn't find anything else, will find the setTimeout function registered by the engine, and runs it. The engine then does whatever it wants to do with that - hopefully, something that complies with the behaviours described in the current ECMAScript standard.
I'm reading DOM SPEC, and I meet the realm and I don't know what is this. According the SPEC said, it's a something of ECMA. I have learned JS, but I haven't learned about realm!
In addition, a part of content in constructing events section , To create an event using eventInterface, If I'm not mistaken eventInterface means this, but I don't found that need to give realm! Who gives the eventinterface a realm? It is chrome's blink??
From https://tc39.es/ecma262/#sec-code-realms:
Before it is evaluated, all ECMAScript code must be associated with a
realm. Conceptually, a realm consists of a set of intrinsic objects, an ECMAScript global environment, all of the ECMAScript code
that is loaded within the scope of that global environment, and other
associated state and resources.
It is perfectly ok that you did not hear about realm. As a developer we can not create it, a JS engine controls realm creation when starts to execute a code.
When you create an event with new Event(), you create an object in JS and a realm is just a place where an event object is placed.
I would like to implement a unique ID generator backed by browser's local storage. My concern is that the ++ operator for the storage DOM object is not implemented to run atomically.
Consider:
function generateUniqueID() {
if(!localStorage.generator) {
localStorage.generator = 0;
}
return localStorage.generator++;
}
Could people please comment if this code would run without any concurrency issues and generate unique IDs across multiple browser tabs hammering this generateUniqueID function?
According to W3C Web Storage Recommendation (see here), §4.5 "Threads":
Because of the use of the storage mutex, multiple browsing contexts will be able to access the local storage areas simultaneously in such a manner that scripts cannot detect any concurrent script execution.
Thus, the length attribute of a Storage object, and the value of the various properties of that object, cannot change while a script is executing, other than in a way that is predictable by the script itself.
Which means to me is that the mutex is placed on first access (read or write) of the script to localStorage and kept until this event loop entry execution returns. Effectively, we have exclusive access to the localStorage for the duration of the execution chain.
I would imagine, if await/async are used, it would break the execution chain, and make the code executed across multiple event loop entries, thus breaking this contract. Even though the source code block looks monolithic. Beware.
The answer to the question is: Yes, the code in question would behave correctly, providing the browser keeps to the W3C recommendation. This is despite the fact that the "test" if(!localStorage.generator) and the "increment" localStorage.generator++ are in the different lines and in most other execution environments are not guaranteed to execute atomically.
It is said that Chrome compiles Javascript 'on the fly' (Just In Time). I don't understand what the JIT part actually means here? As far as I understand, the browser will take all of the JS code, compile it, and then execute it. It can't really do compilation in steps, as that would be more like interpreting (Does V8 interpret the code too at any point?).
Also, I want to understand why is Javascript called non-blocking? In reality, isn't the run-time environment (V8) the one which actually makes JS 'non-blocking'? Javascript is single-threaded, and as per my understanding, the thread dies as soon as all synchronous code is finished executing. It is the event loop that actually keeps Javascript 'alive' by 'bringing back the dead thread into life'. And the event loop is actually not part of the Javascript specification.
(Or is it that the global execution context is always present in the execution stack queue and whenever a new event handler is to be executed, a new execution stack is created and popped on top of the queue, hence the thread never truly dies)?
Does V8 interpret the code too at any point?).
Yes it does. Turning an AST into bytecode takes time, especially for such a dynamic language as JS. If a function only runs once or twice, it makes no sense to spend a lot of time to generate optimal bytecode, wereas interpreting the AST would be faster. Thats why most engines actually interpret the code, and then start building compiled versions for hot functions.
Also, I want to understand why is Javascript called non-blocking? In reality, isn't the run-time environment (V8) the one which actually makes JS 'non-blocking'?
Yes exactly. JavaScripts execution model is observably synchronous. The asynchrony comes from events coming in from the outside, e.g. from the engine
Javascript is single-threaded, and as per my understanding, the thread dies as soon as all synchronous code is finished executing. It is the event loop that actually keeps Javascript 'alive' by 'bringing back the dead thread into life'.
Yes, exactly.
And the event loop is actually not part of the Javascript specification.
It is. It is just not named event loop. The spec defines that agents work on task queues. Whats inside the task queue depends on the actual usecase of the engine, for browsers some of these queues are defined by the Web Spec.
I highly recommend reading some of the posts at https://v8.dev/blog/, especially this linked article.
I've been reading about web workers in HTML5, but I know JavaScript is single-threaded.
How are web workers doing multi-threaded work then? or how are they simulating it if it's not truly multi-threaded?
As several comments have already pointed out, Workers really are multi-threaded.
Some points which may help clarify your thinking:
JavaScript is a language, it doesn't define a threading model, it's not necessarily single threaded
Most browsers have historically been single threaded (though that is changing rapidly: IE, Chrome, Firefox), and most JavaScript implementations occur in browsers
Web Workers are not part of JavaScript, they are a browser feature which can be accessed through JavaScript
A bit late, but I just asked myself the same question and I came up with the following answer:
Javascript in browsers is always single-threaded, and a fundamental consequence is that "concurrent" access to variables (the principal headache of multithreaded programming) is actually not concurrent; this is true with the exception of webworkers, which are actually run in separate threads and concurrent access to variables must be dealt with in a somewhat explicit way.
I am not a JavaScript ninja, but I too was convinced that JavaScript in browser is provided as a single threaded process, without paying much attention to whether it was true or to the rationale behind this belief.
A simple fact that supports this assumption is that when programming in JavaScript you don't have to care about concurrent access to shared variables. Every developer, without even thinking of the problem, writes code as if every access to a variable is consistent.
In other words, you don't need to worry about the so called Memory model.
Actually there is no need of looking at WebWorkers to involve parallel processing in JavaScript. Think of an (asynchronous) AJAX request. And think how carelessly you would handle concurrent access to variables:
var counter = 0;
function asyncAddCounter() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4) {
counter++;
}
};
xhttp.open("GET", "/a/remote/resource", true);
xhttp.send();
}
asyncAddCounter();
counter++;
What is the value of counter at the end of the process? It is 2.
It doesn't matter that it is read and written "concurrently", it will never result in a 1. This means that access to counter is always consistent.
If two threads where really accessing the value concurrently, they both could start off by reading 0 and both write 1 in the end.
In browsers, the actual data-fetching of a remote resource is hidden to the developer, and its inner workings are outside the scope of the JavaScript API (what the browser let's you control in terms of JavaScript instructions). As far as the developer is concerned, the result of the network request is processed by the main thread.
In short, the actual carrying out of the request is not visible, but the invocation of the callback (handling the result by custom JavaScript code) is executed by the main thread.
Possibly, if it wasn't for the webworkers, the term "multithreading" wouldn't ever enter the Javascript world.
The execution of the request and the asynchronous invocation of the callback is actually achieved by using event loops, not multithreading. This is true for several browsers and obviously for Node.js. The following are some references, in some cases a bit obsolete, but I guess that the main idea is still retained nowadays.
Firefox: Concurrency model and Event Loop - JavaScript | MDN
Chrome uses libevent in certain OS.
IE: Understanding the Event Model (Internet Explorer)
This fact is the reason why JavaScript is said to be Event-driven but not multithreaded.
Notice that JavaScript thus allows for asynchronous idioms, but not parallel execution of JavaScript code (outside webworkers). The term asynchronous just denotes the fact that the result of two instructions might be processed in scrambled order.
As for WebWorkers, they are JavaScript APIs that give a developer control over a multithreaded process.
As such, they provide explicit ways to handle concurrent access to shared memory (read and write values in different threads), and this is done, among the others, in the following ways:
you push data to a web worker (which means that the new thread reads data) by structured clone: The structured clone algorithm - Web APIs | MDN. Essentially there is no "shared" variable, instead the new thread is given a fresh copy of the object.
you push data to a web worker by transferring ownership of the value: Transferable - Web APIs | MDN. This means that the just one thread can read its value at any time.
as for the results returned by the web workers (how they "write"), the main thread access the results when prompted to do so (for instance with the instruction thisWorker.onmessage = function(e) {console.log('Message ' + e.data + ' received from worker');}). It must be by means of the usual Event Loop, I must suppose.
the main thread and the web worker access a truly shared memory, the SharedArrayBuffer, which is thread-safely accessed using the Atomic functions. I found this clearly exposed in this article: JavaScript: From Workers to Shared Memory
note: webworkers cannot access the DOM, which is truly shared!
You spawn a .js file as a "worker", and it runs processes in a separate thread. You can pass JSON data back and forth between it and the "main" thread. Workers don't have access to certain things like the DOM, though.
So if, say, you wanted to solve complicated math problems, you could let the user enter things into the browser, pass those variables off to the worker, let it do the computation in the background while in the main thread you let the user do other things, or show a progress bar or something, and then when the worker's done, it passes the answer back, and you print it to the page. You could even do multiple problems asynchronously and pass back the answers out of order as they finish. Pretty neat!
The browser kicks of a thread with the javascript you want to execute. So its a real thread, with this web workers thing, your js is no longer single-threaded.
The answer that claimed that "JavaScript is a language, it doesn't define a threading model, it's not necessarily single-threaded" is directly copy-pasted from a medium article... and it confuses without solving the doubt.
It's not necessarily single-threaded, like all other languages. YES... BUT
Javascript is a LANGUAGE meant for Single-threaded programming, and that is the beauty of it and makes it simple and easy to implement.
It is designed around a single Call stack.
Maybe in the future, with new implementations, it will become a Language for multi-threaded programming... but for now, Mehhhhhh.
The Node V8 is still single-threaded, yet it achieves multi-threaded capabilities by creating worker threads on LIBUV which is written in C++.
Same way, even though Javascript is not meant for Multithreading you can achieve limited multithreading by using Browser APIs.
Every time you open a TAB on a browser, it creates a new thread, and the process is the same with web workers.
It works internally BUT does not have access to any window objects.
Yes, People may call it Multithreaded if it makes em Happy,
But in 2021 the Answer is
"JS is meant for Single-threaded programming,(or a single-threaded language) but limited multi-threading can be achieved by using Browser APIs such as Web Workers"
Actually the main confusion, I think here, comes that people are finding clever ways to do things concurrently. If you think about it JavaScript is clearly not multithreaded and yet we have ways to do things in parallel, so what is going on?
Asking the right question is what will bring the answer here. Who is responsible for the threads? There is one answer above, saying that JS is just a language, not a threading model. Completely true!JavaScript has nothing to do with it. The responsibility falls on V8. Check this link for more information -> https://v8.dev/
So V8 is allowing a single thread per JS Context, which means, no matter how hard you try, spawning a new thread is simply impossible. Yet people spawn so-called workers and we get confused. For this to be answered, I ask you the following. Is it possible to maybe start 2 V8 and both of them to interpret some JS code? Precisely the solution to our problem. Workers communicate with messages because their context is different. They are other things that don't know anything about our context, therefore they need some information that comes in the form of a message.
As we are all aware, JavaScript is single-threaded: all code is queued and executed in a sequence.
Using Web Workers, we can run JavaScript processes concurrently (or at least, as close to concurrently as this language allows). The primary benefit of this approach is to handle the manipulation of data in background threads without interfering with the user-interface.
Using web worker:
Web Workers allow you to run JavaScript in parallel on a web page, without blocking the user interface.
Web workers executes in separate thread
Need to host all the worker code in separate file
They aren’t automatically garbage collected, So you need to control them.
To run worker use worker.postMessage(“”);
To stop worker there are two methods terminate() from caller code
and close() from Worker itself
Instantiating a worker will cost some memory.
Web Workers run in an isolated thread. As a result, the code that they execute needs to be contained in a separate file. But before we do that, the first thing to do is create a new Worker object in your main page. The constructor takes the name of the worker script:
var worker = new Worker('task.js');
If the specified file exists, the browser will spawn a new worker thread, which is downloaded asynchronously. The worker will not begin until the file has completely downloaded and executed. If the path to your worker returns an 404, the worker will fail silently.
After creating the worker, start it by calling the postMessage() method:
worker.postMessage(); // Start the worker.
Communicating with a Worker via Message Passing
Communication between a work and its parent page is done using an event model and the postMessage() method. Depending on your browser/version, postMessage() can accept either a string or JSON object as its single argument. The latest versions of the modern browsers support passing a JSON object.
Below is a example of using a string to pass 'Hello World' to a worker in doWork.js. The worker simply returns the message that is passed to it.
Main script:
var worker = new Worker('doWork.js');
worker.addEventListener('message', function(e) {
console.log('Worker said: ', e.data);
}, false);
worker.postMessage('Hello World'); // Send data to our worker.
doWork.js (the worker):
self.addEventListener('message', function(e) {
self.postMessage(e.data); // Send data back to main script
}, false);
When postMessage() is called from the main page, our worker handles that message by defining an onmessage handler for the message event. The message payload (in this case 'Hello World') is accessible in Event.data. This example demonstrates that postMessage() is also your means for passing data back to the main thread. Convenient!
References:
http://www.tothenew.com/blog/multi-threading-in-javascript-using-web-workers/
https://www.html5rocks.com/en/tutorials/workers/basics/
https://dzone.com/articles/easily-parallelize-jobs-using-0