How JS determine when to call Callback function? - javascript

I am wondering how JavaScript callbacks work. I specifically can't understand how asynchronous XmlHttpRequest works. How can JS determine that server returned some value (in one thread), and when to call callback method? Is it build on timers?

A very similar question was answered here in more detail.
The basic answer is that the underlying networking is happening at the OS level where there can be threads or some type of notifications when incoming networking packets arrive. When the result has completed, an event is added to the javascript event queue. When that event gets to the top of the event queue and javascript is ready to act on it, the proper javascript ajax event will be triggered which starts the chain of javascript that results in calling your callback.
There may some timers involved for timeouts, but timers are not used to know when the ajax response has arrived. That's based on the OS level networking support that the browser uses.

You wouldn't use timers since you couldn't tell when they should trigger.
I'd imagine it is using some sort of stack/queue [list or table] to keep track of calls and popping the response function off depending on the returned info telling you which request it was responding to.

Remember, javascript runs in an environment. That environment is not single threaded. When an xhr returns the browser (the environment) notifies the javascript engine that the xhr returned, and it in turn will execute the callback. Also remember that even though the programming model of javascript for the user is single threaded, javascript itself does not have to be.

Basically..
Whenever there's no javascript executing at the moment, events triggering from settimeout and responses to XmlHttpRequest are checked. They are indeed added to an event queue.
The interesting effect of this, is that as long as javascript is currently executing, events like these will never be triggered.

The asynchronous nature of the XmlHttpRequest is provided at lower level than javascript (by the browser). The callback function is initiated by the browser signalling to the javascript engine that the request is complete.

Related

Mechanics of Javascript Asynchronous execution

Can someone please explain the mechanics behind the asynchronous behavior of javascript, specifically when it comes to a .subscribe(), or provide a link that would help me understand what's really going on under the hood?
Everything appears to be single-threaded, then I run into situations that make it either multi-threaded, or seem multi-threaded, because I still can't shake this feeling I'm being fooled.
Everything seems to run perfectly synchronously, one instruction at a time, until I call .subscribe(). Then, suddenly, something happens - it returns immediately, and somehow the next outside function runs even though the subscription code has not yet. This feels asynchronous to me, how does the browser keep things straight - if not threads, can someone please explain the mechanics in play that is allowing this to occur?
I also notice something happens with debug stepping, I can't step in to the callback, I can only put a breakpoint within it. In what order should I really expect things to occur?
Your Javascript itself runs single threaded unless you're talking about WebWorkers (in the browser) or WorkerThreads (in nodejs).
But, many functions you call or operations you initiate in Javascript can run separate from that single threaded nature of your Javascript. For example, networking is all non-blocking and asynchronous. That means that when you make a call to fetch() in the browser of http.get() in nodejs, you are initiating an http request and then the mechanics of making that request and receiving the response are done independent of your Javascript. Here are some example steps:
You make a call to fetch() in the browser to make an http request to some other host.
The code behind fetch, sends out the http request and then immediately returns.
Your Javascript continues to execute (whatever you had on the lines of code immediately after the fetch() call will execute.
Sometime later, the response from the fetch() call arrives back on the network interface. Some code (internal to the Javascript environment) and independent from your single thread of Javascript sees that there's incoming data to read from the http response. When that code has gathered the http response, it inserts an event into the Javascript event queue.
When the single thread of Javascript has finished executing whatever event it was executing, it checks the event queue to see if there's anything else to do. At some point, it will find the event that signified the completion of the previous fetch() call and there will be a callback function associated with that event. It will call that callback which will resolve the promise associated with the fetch() call which will cause your own Javascript in the .then() handler for that promise to run and your Javascript will be presented the http response you were waiting for.
Because these non-blocking, asynchronous operations (such as networking, timers, disk I/O, etc...) all work in this same manner and can proceed independent of your Javascript execution, they can run in parallel with your Javascript execution and many of them can be in flight at the same time while your Javascript is doing other things. This may sometimes give the appearance of multiple threads and there likely are some native code threads participating in some of this, though there is still only one thread of your Javascript (as long as we're not talking about WebWorkers or WorkerThreads).
The completion of these asynchronous operations is then synchronized with the single thread of Javascript via the event queue. When they finish, they place an event in the event queue and when the single thread of Javascript finishes what it was last doing, it grabs the next event from the event queue and processes it (calling a Javascript callback).
I also notice something happens with debug stepping, I can't step in to the callback, I can only put a breakpoint within it. In what order should I really expect things to occur?
This is because the callback isn't called synchronously. When you step over the function that you passed a callback to, it executes that function and it returns. Your callback is not yet called. So, the debugger did exactly what you asked it to do. It executed that function and that function returned. The callback has not yet executed. Your are correct that if you want to see the asynchronous callback execute, you need to place a breakpoint in it so when it does get called some time in the future, the debugger will then stop there and let you step further. This is a complication of debugging asynchronous things, but you get used to it after awhile.
Everything appears to be single-threaded, then I run into situations that make it either multi-threaded, or seem multi-threaded, because I still can't shake this feeling I'm being fooled.
This is because there can be many asynchronous operations in flight at the same time as they aren't running your Javascript while they are doing their thing. So, there's still only one thread of Javascript, even though there are multiple asynchronous operations in flight. Here's a code snippet:
console.log("starting...");
fetch(host1).then(result1 => { console.log(result1)});
fetch(host2).then(result2 => { console.log(result2)});
fetch(host3).then(result3 => { console.log(result3)});
fetch(host4).then(result4 => { console.log(result4)});
console.log("everything running...");
If you run this, you will see something like this in the console:
starting...
everything running...
result1
result2
result3
result4
Actually, the 4 results may be in any order relative to one another, but they will be after the first two lines of debug output. In this case, you started four separate fetch() operations and they are running independent of your Javascript. In fact, your Javascript is free to do other things while they run. When they finish and when your Javascript isn't doing anything else, your four .then() handlers will each get called at the appropriate time.
When the networking behind each fetch() operation finishes, it will insert an event in the Javascript event queue and if your Javascript isn't doing anything at the time, the insertion of that event will wake it up and cause it to process that completion event. If it was doing something at the time, then when it finishes that particular piece of Javascript and control returns back to the system, it will see there's an event waiting in the event queue and will process it, calling your Javascript callback associated with that event.
Search for articles or videos on the “JavaScript Event Loop”. You’ll find plenty of them. Probably go through a few of them and it will start to make sense (particularly the single-threaded aspect of it)
I found this one with a quick search, and it does a good, very high-level walkthrough.
The JavaScript Event Loop explained
The main impact of JavaScript single threading is that your code is never pre-emptively interrupted to execute code on another thread.
It may seem that some code is being skipped, but close attention to the syntax will show that what is being “skipped” is just a callback function or closure to be called at a time in the future (when it will be placed into the event queue and processed single-threadedly, itself).
Careful, it can be tricky to follow nested callbacks.
Probably also look into Promises and async /await (‘just syntactic convenience on the event loop, but can really help code readability)

How does Node.js process incoming requests?

In order to dive into more complex concepts about Node.js, I am doing some research to make sure I understand the principles about the language and the basic building blocks it´s build upon.
As far as I´m concerned, Node.js relies in the reactor pattern to process each incoming request. This algorithm is based in the Event Demultiplexer algorithm. The second one is in charge of processing the request operation and it´s resources and then, once the operation is finished, it adds the 'result' to the Event Queue. After this process, the Event Loop is now in charge of executing the Handlers for each event.
As a single threaded process, I´m struggling to understand how does the Event demultiplexer handle all the incoming operations if the event loop is managing all the event queue tasks in parallel...
I´ve found this in the Node.js documentation:
Since most modern kernels are multi-threaded, they can handle multiple
operations executing in the background. When one of these operations
completes, the kernel tells Node.js so that the appropriate callback
may be added to the poll queue to eventually be executed. We'll
explain this in further detail later in this topic.
Does this mean that the Event Demultiplexer tasks are not handled by Node and that Node just gets the result in order to add it to the Event Queue? Doesn´t that mean that Node is not single threaded?
I've found some useful graphics on the web that clearly explain the path that each request follows, but It´s really hard to find some explaining the actual timing in which the thread processes each one.
In node.js, it runs your Javascript in a single thread (assuming we're not talking about worker threads or clustering). But, many asynchronous operations in the node.js built-in library such as file I/O or some crypto operations use their own threads to accomplish their task. So, when you call an asynchronous operations such as fs.open() to open a file, it transitions to native code, grabs a thread from an internal thread pool and that thread goes about opening the file. The fs.open() function then returns back to your Javascript (while the thread continues in the background). Sometime later when it finishes its task, the internal thread inserts an event into the nodejs event queue and when nodejs has cycles to check the event queue, it will find that event and run the Javascript callback associated with it to provide the asynchronous result back to your Javascript.
So, even though threads may be involved, your Javascript is all still single threaded through the event loop.
So, nodejs does use native code threads for some internal native code operations. Other things like networking and timers are implemented without threads.
Then if I send a request to fetch data from a database in Node, how does the Event Demultiplexer process It? Does the main thread stop the event loop to handle that operation and then resumes after the event handler is queued?
These terms like "Event Demultiplexor" are things you are applying to node.js. They are not something that node.js uses at all so I'm not entirely sure what you're asking.
Node.js runs one event at a time. It has no interrupt-driven abilities. So, it runs one event until that event returns control back to the event loop (by issuing a return from the callback that started everything). Now, the original event may not be complete - it may be doing something asynchronous that will trigger another event to announce completion, but it has finished running Javascript for now and has returned control back to the event loop.
When an incoming Fetch request (which is just an incoming http request) arrives at the server, it is first queued by the OS. Then, when the event loop has a chance to see it, it is added to the node.js event queue and is served in FIFO order when other events that were before it are done processing. Now, the nodejs event loop is not as simple as a single event queue. It actually has several different queues for different types of work and has priorities for what gets to run first, but at the simplest level, you can start out thinking of it as a single FIFO queue. And, nothing is ever interrupted.
Pull an event out of the event queue, run the Javascript callback associated with it. When that callback returns back to the event loop, get the next event and do the same.
Events may be added to the event queue either by native code threads (like might be done with file I/O or some crypto operations) or via some polling mechanisms built into the event loop as part of the event loop cycle it checks for certain things that are ready to run (as with networking and timers).

How is JavaScript never blocking? [duplicate]

I'm not a Node programmer, but I'm interested in how the single-threaded non-blocking IO model works.
After I read the article understanding-the-node-js-event-loop, I'm really confused about it.
It gave an example for the model:
c.query(
'SELECT SLEEP(20);',
function (err, results, fields) {
if (err) {
throw err;
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<html><head><title>Hello</title></head><body><h1>Return from async DB query</h1></body></html>');
c.end();
}
);
Que: When there are two requests A(comes first) and B since there is only a single thread, the server-side program will handle the request A firstly: doing SQL querying is asleep statement standing for I/O wait. And The program is stuck at the I/O waiting, and cannot execute the code which renders the web page behind. Will the program switch to request B during the waiting? In my opinion, because of the single thread model, there is no way to switch one request from another. But the title of the example code says that everything runs in parallel except your code.
(P.S I'm not sure if I misunderstand the code or not since I have
never used Node.)How Node switch A to B during the waiting? And can
you explain the single-threaded non-blocking IO model of Node in a
simple way? I would appreciate it if you could help me. :)
Node.js is built upon libuv, a cross-platform library that abstracts apis/syscalls for asynchronous (non-blocking) input/output provided by the supported OSes (Unix, OS X and Windows at least).
Asynchronous IO
In this programming model open/read/write operation on devices and resources (sockets, filesystem, etc.) managed by the file-system don't block the calling thread (as in the typical synchronous c-like model) and just mark the process (in kernel/OS level data structure) to be notified when new data or events are available. In case of a web-server-like app, the process is then responsible to figure out which request/context the notified event belongs to and proceed processing the request from there. Note that this will necessarily mean you'll be on a different stack frame from the one that originated the request to the OS as the latter had to yield to a process' dispatcher in order for a single threaded process to handle new events.
The problem with the model I described is that it's not familiar and hard to reason about for the programmer as it's non-sequential in nature. "You need to make request in function A and handle the result in a different function where your locals from A are usually not available."
Node's model (Continuation Passing Style and Event Loop)
Node tackles the problem leveraging javascript's language features to make this model a little more synchronous-looking by inducing the programmer to employ a certain programming style. Every function that requests IO has a signature like function (... parameters ..., callback) and needs to be given a callback that will be invoked when the requested operation is completed (keep in mind that most of the time is spent waiting for the OS to signal the completion - time that can be spent doing other work). Javascript's support for closures allows you to use variables you've defined in the outer (calling) function inside the body of the callback - this allows to keep state between different functions that will be invoked by the node runtime independently. See also Continuation Passing Style.
Moreover, after invoking a function spawning an IO operation the calling function will usually return control to node's event loop. This loop will invoke the next callback or function that was scheduled for execution (most likely because the corresponding event was notified by the OS) - this allows the concurrent processing of multiple requests.
You can think of node's event loop as somewhat similar to the kernel's dispatcher: the kernel would schedule for execution a blocked thread once its pending IO is completed while node will schedule a callback when the corresponding event has occured.
Highly concurrent, no parallelism
As a final remark, the phrase "everything runs in parallel except your code" does a decent job of capturing the point that node allows your code to handle requests from hundreds of thousands open socket with a single thread concurrently by multiplexing and sequencing all your js logic in a single stream of execution (even though saying "everything runs in parallel" is probably not correct here - see Concurrency vs Parallelism - What is the difference?). This works pretty well for webapp servers as most of the time is actually spent on waiting for network or disk (database / sockets) and the logic is not really CPU intensive - that is to say: this works well for IO-bound workloads.
Well, to give some perspective, let me compare node.js with apache.
Apache is a multi-threaded HTTP server, for each and every request that the server receives, it creates a separate thread which handles that request.
Node.js on the other hand is event driven, handling all requests asynchronously from single thread.
When A and B are received on apache, two threads are created which handle requests. Each handling the query separately, each waiting for the query results before serving the page. The page is only served until the query is finished. The query fetch is blocking because the server cannot execute the rest of thread until it receives the result.
In node, c.query is handled asynchronously, which means while c.query fetches the results for A, it jumps to handle c.query for B, and when the results arrive for A arrive it sends back the results to callback which sends the response. Node.js knows to execute callback when fetch finishes.
In my opinion, because it's a single thread model, there is no way to
switch from one request to another.
Actually the node server does exactly that for you all the time. To make switches, (the asynchronous behavior) most functions that you would use will have callbacks.
Edit
The SQL query is taken from mysql library. It implements callback style as well as event emitter to queue SQL requests. It does not execute them asynchronously, that is done by the internal libuv threads that provide the abstraction of non-blocking I/O. The following steps happen for making a query :
Open a connection to db, connection itself can be made asynchronously.
Once db is connected, query is passed on to the server. Queries can be queued.
The main event loop gets notified of the completion with callback or event.
Main loop executes your callback/eventhandler.
The incoming requests to http server are handled in the similar fashion. The internal thread architecture is something like this:
The C++ threads are the libuv ones which do the asynchronous I/O (disk or network). The main event loop continues to execute after the dispatching the request to thread pool. It can accept more requests as it does not wait or sleep. SQL queries/HTTP requests/file system reads all happen this way.
Node.js uses libuv behind the scenes. libuv has a thread pool (of size 4 by default). Therefore Node.js does use threads to achieve concurrency.
However, your code runs on a single thread (i.e., all of the callbacks of Node.js functions will be called on the same thread, the so called loop-thread or event-loop). When people say "Node.js runs on a single thread" they are really saying "the callbacks of Node.js run on a single thread".
Node.js is based on the event loop programming model. The event loop runs in single thread and repeatedly waits for events and then runs any event handlers subscribed to those events. Events can be for example
timer wait is complete
next chunk of data is ready to be written to this file
theres a fresh new HTTP request coming our way
All of this runs in single thread and no JavaScript code is ever executed in parallel. As long as these event handlers are small and wait for yet more events themselves everything works out nicely. This allows multiple request to be handled concurrently by a single Node.js process.
(There's a little bit magic under the hood as where the events originate. Some of it involve low level worker threads running in parallel.)
In this SQL case, there's a lot of things (events) happening between making the database query and getting its results in the callback. During that time the event loop keeps pumping life into the application and advancing other requests one tiny event at a time. Therefore multiple requests are being served concurrently.
According to: "Event loop from 10,000ft - core concept behind Node.js".
The function c.query() has two argument
c.query("Fetch Data", "Post-Processing of Data")
The operation "Fetch Data" in this case is a DB-Query, now this may be handled by Node.js by spawning off a worker thread and giving it this task of performing the DB-Query. (Remember Node.js can create thread internally). This enables the function to return instantaneously without any delay
The second argument "Post-Processing of Data" is a callback function, the node framework registers this callback and is called by the event loop.
Thus the statement c.query (paramenter1, parameter2) will return instantaneously, enabling node to cater for another request.
P.S: I have just started to understand node, actually I wanted to write this as comment to #Philip but since didn't have enough reputation points so wrote it as an answer.
if you read a bit further - "Of course, on the backend, there are threads and processes for DB access and process execution. However, these are not explicitly exposed to your code, so you can’t worry about them other than by knowing that I/O interactions e.g. with the database, or with other processes will be asynchronous from the perspective of each request since the results from those threads are returned via the event loop to your code."
about - "everything runs in parallel except your code" - your code is executed synchronously, whenever you invoke an asynchronous operation such as waiting for IO, the event loop handles everything and invokes the callback. it just not something you have to think about.
in your example: there are two requests A (comes first) and B. you execute request A, your code continue to run synchronously and execute request B. the event loop handles request A, when it finishes it invokes the callback of request A with the result, same goes to request B.
Okay, most things should be clear so far... the tricky part is the SQL: if it is not in reality running in another thread or process in it’s entirety, the SQL-execution has to be broken down into individual steps (by an SQL processor made for asynchronous execution!), where the non-blocking ones are executed, and the blocking ones (e.g. the sleep) actually can be transferred to the kernel (as an alarm interrupt/event) and put on the event list for the main loop.
That means, e.g. the interpretation of the SQL, etc. is done immediately, but during the wait (stored as an event to come in the future by the kernel in some kqueue, epoll, ... structure; together with the other IO operations) the main loop can do other things and eventually check if something happened of those IOs and waits.
So, to rephrase it again: the program is never (allowed to get) stuck, sleeping calls are never executed. Their duty is done by the kernel (write something, wait for something to come over the network, waiting for time to elapse) or another thread or process. – The Node process checks if at least one of those duties is finished by the kernel in the only blocking call to the OS once in each event-loop-cycle. That point is reached, when everything non-blocking is done.
Clear? :-)
I don’t know Node. But where does the c.query come from?
The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible. Think of event loop as the manager.
New requests are sent into a queue and watched by the synchronous event demultiplexer. As you see each operations handler is also registered.
Then those requests are sent to the thread pool (Worker Pool) synchronously to be executed. JavaScript cannot perform asynchronous I/O operations. In browser environment, browser handles the async operations. In node environment, async operations are handled by the libuv by using C++. Thread's pool default size is 4, but it can be changed at startup time by setting the UV_THREADPOOL_SIZE environment variable to any value (maximum is 128). thread pool size 4 means 4 requests can get executed at a time, if event demultiplexer has 5 requsts, 4 would be passed to thread pool and 5th would be waiting. Once each request gets executed, result is returned to the `event demultiplexer.
When a set of I/O operations completes, the Event Demultiplexer pushes a set of corresponding events into the Event Queue.
handler is the callback. Now event loop keeps an eye on the event queue, if there is something ready, it is pushed to stack to execute the callback. Remember eventually callbacks get executed on stack. Note that some callbacks has priorities on other, the event loop does pick the callbacks based on their priorities.
For those who seek short answer and don't want to go to the deepest levels of Node.js internals.
Node.js is not single threaded, it runs on 5 threads by default.
Yes, the only single thread is for actual JavaScript processing, but it always switches from function to function.
It sends SQL query to a database and lets it wait in other thread, while single threaded Node.js continues to compute some other code ready to be computed.
If you wish more explanations, there are good articles about Event Loop, Worker Pool and the whole libuv documentation.

Are event handlers guaranteed to complete before AJAX callbacks are invoked?

Suppose I have a event handler which makes two AJAX calls to the server:
$("#foo").click(function(){
$.get("bar", function(){ alert("Hello"); });
$.get("baz", function(){ alert("World"); });
});
I realize that the order in which the callbacks are invoked is nondeterministic, since it depends on how long each request takes, etc.
But here's my question: is it guaranteed that I'll reach the end of my event handler before either of the callback functions are invoked? I've read that all Javascript for a page executes in a single thread, so I think that implies that my click event handler is guaranteed to complete before any of the callbacks can be invoked.
Is this correct? Or is it possible that the first request might be complete AND the first callback executed before we even get to the end of our event handler?
Yes, this is guaranteed and you are right - there is just a single thread (ignoring web-workers for the moment). When a piece of JavaScript code executes (occupies the execution thread) and an AJAX callback arrives (or any other GUI event, timeout, etc.) it is queued and waits until the execution thread is free (current piece of code finishes).
JavaScript engine will never interrupt running code to handle incoming event - events will always gently wait in a queue. This is the reason why the GUI appears to be freezing when CPU-intensive code is executing - no events are handled. Also this is why synchronous AJAX requests are bad.
See also
JavaScript equivalent of SwingUtilities.invokeLater()
"atomic" operation desturbed by asynchronous ajax callbacks
Are there any atomic javascript operations to deal with Ajax's asynchronous nature?
how is async programming (promises) implemented in javascript? isn't javascript a ui-threaded environment?
Yes, JavaScript is single threaded, so your execution will never get preempted.
Asynchronous callbacks and events work the same way; your handler for mousedown is guaranteed to finish before your handler for a mouseup, even if your mousedown handler takes 2 seconds and you let the mouse go immediately.
The same goes for an AJAX callback, it gets put into the same (kind of) queue as events waiting to be processed
An interesting twist to this would be instead of $.get(), lets say we were using promises that we get from somewhere else (i.e. the actual async call was made elsewhere) (-Why would we have such a situation? Well maybe we have a memoized query function.)
Now if one were using jQuery promises, the callbacks would be invoked synchronously if already resolved. Is that ever an issue? Well depends on your requirement. If it does then you could wrap the callback code in a setTimeout(cb, 0).
On the other hand, what if you wanted the callbacks to be preempted? See my examples here
I realize that the order in which the callbacks are invoked is nondeterministic, since it depends on how long each request takes, etc.
In the way you have written it yes.. but there are ways to organize and control this.. namely deffereds and promises.
Here is a good overview: http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/
Proper use of them will ensure that you won't run into whatever problem you seem to be trying to avoid.
**
As #Juan has pointed out, this isn't the black and white answer for the question you asked. I'm just trying to point you in different directions or ways to look at the same problem so you can define your expected behavior more explicitly.

JavaScript and single-threadedness

I always hear that JavaScript is single-threaded; that when JavaScript is executed, it's all run in the same global mosh pit, all in a single thread.
While that may be true, that single execution thread may spawn new threads, asynchronousy reqeiving data back to the main thread, correct? For example, when an XMLHttpRequest is sent, doesn't the browser create a new thread that performs the HTTP transaction, then invoke callbacks back in the main thread when the XMLHttpRequest returns?
What about timers--setTimeout and setInterval? How do those work?
Is this single-threadedness the result of the language? What has stopped JavaScript from having multi-threaded execution before the new Web Workers draft?
XMLHttpRequest, notably, does not block the current thread. However, its specifics within the runtime are not outlined in any specification. It may run in a separate thread or within the current thread, making use of non-blocking I/O.
setTimeout and setInterval set timers that, when run down to zero, add an item for execution, either a line of code of a function/callback, to the execution stack, starting the JavaScript engine if code execution has stopped. In other words, they tell the JavaScript engine to do something after it has finished doing whatever it's doing currently. To see this in action, set multiple setTimeout(s) within one method and call it.
Your JavaScript itself is single-threaded. It may, however, interact with other threads in the browser (which is frequently written with something like C and C++). This is how asynchronous XHR's work. The browser may create a new thread (or it may re-use an existing one with an event loop.)
Timers and intervals will try to make your JavaScript run later, but if you have a while(1){ ; } running don't expect a timer or interval to interrupt it.
(edit: left something out.)
The single-threadedness is largely a result of the ECMA specification. There's really no language constructs for dealing with multiple threads. It wouldn't be impossible to write a JavaScript interpreter with multiple threads and the tools to interact with them, but no one really does that. Certainly no one will do it in a web browser; it would mess everything up. (If you're doing something server-side like Node.js, you'll see that they have eschewed multithreading in the JavaScript proper in favor of a snazzy event loop, and optional multi-processing.)
See this post for a description of how the javascript event queue works, including how it's related to ajax calls.
The browser certainly uses at least one native OS thread/process to handle the actual interface to the OS to retrieve system events (mouse, keyboard, timers, network events, etc...). Whether there is more than one native OS-level thread is dependent upon the browser implementation and isn't really relevant to Javascript behavior. All events from the outside world go through the javascript event queue and no event is processed until a previous javascript thread of execution is completed and the next event is then pulled from the queue given to the javascript engine.
Browser may have other threads to do the job but your Javascript code will still be executed in one thread. Here is how it would work in practice.
In case of time out, browser will create a separate thread to wait for time out to expire or use some other mechanism to implement actual timing logic. Then timeout expires, the message will be placed on main event queue that tells the runtime to execute your handler. and that will happen as soon as message is picked up by main thread.
AJAX request would work similarly. Some browser internal thread may actually connect to server and wait for the response and once response is available place appropriate message on main event queue so main thread executes the handler.
In all cases your code will get executed by main thread. This is not different from most other UI system except that browser hides that logic from you. On other platforms you may need to deal with separate threads and ensure execution of handlers on UI thread.
Putting it more simply than talking in terms of threads, in general (for the browsers I'm aware of) there will only be one block of JavaScript executing at any given time.
When you make an asynchronous Ajax request or call setTimeout or setInterval the browser may manage them in another thread, but the actual JS code in the callbacks will not execute until some point after the currently executing block of code finishes. It just gets queued up.
A simple test to demonstrate this is if you put a piece of relatively long running code after a setTimeout but in the same block:
setTimeout("alert('Timeout!');", 5);
alert("After setTimeout; before loop");
for (var i=0, x=0; i < 2000000; i++) { x += i };
alert("After loop");
If you run the above you'll see the "After setTimeout" alert, then there'll be a pause while the loop runs, then you'll see "After loop", and only after that will you see "Timeout!" - even though clearly much longer than 5ms has passed (especially if you take a while to close the first alert).
An often-quoted reason for the single-thread is that it simplifies the browser's job of rendering the page, because you don't get the situation of lots of different threads of JavaScript all trying to update the DOM at the same time.
Javascript is a language designed to be embedded. It can and has been used in programs that execute javascript concurrently on different operating threads. There isn't much demand for an embedded language to explicitly control the creation of new threads of execution, but it could certainly be done by providing a host object with the required capabilities. The WHATWG actually includes a justification for their decision not to push a standard concurrent execution capability for browsers.

Categories

Resources