Do DOM Events Always Run Single Threaded? - javascript

So I answered a question recently and OP asked if I could add the following about DOM events to my answer:
Maybe you could also add to your answer that not only they are executed first, but the subsequent event is blocked until the first one finishes.
Well, can I add that? Do I know that with DOM events will run one event at a time and will wait for the previous one to finish before the next one starts?
Do I at least know this is always the case in browser JavaScript?
Finding a conclusive answer to this has been surprisingly difficult to be so far, I've expected a "yes" but I just can't find it.
Clarification: I'm not asking about adding other asynchronous handlers inside the handlers, or calling setTimeout or workers and such. All I'm asking is whether or not the order of event handler execution is guaranteed, and that the next one starts only the previous one finished executing ? A good answer would cite a credible source (preferably - a specification). Nothing about threading here.

Yes and no, all JS runs on the same thread, except for web workers, which don't have access to the DOM. http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/
Here's some relevant information on that page
All event handler functions are executed sequentially, and each event is processed completely (including bubbling up through the DOM and performing the default action), before the next event is processed.
However, later on that page, they mention
Race Conditions
Each window (and frame) has its own event queue.
In Opera, every window has its own JavaScript thread. This includes windows in iframes. The consequence is that event handlers initiated from different frames might execute at the same time. If these simultaneous scripts modify shared data (like properties in the top window), we have the possibility of race conditions.
Events all are put into an event queue, and all event handling happens within that same thread. Along with all asynchronous callbacks, like XHR and setTimeout.
Beware of nested events also, since many methods will execute if you fire an event and they could change global state. Example http://jsfiddle.net/rpxZ4/
$('#d1').click(function(){
alert('before ');
$('#d2').trigger('click');
$('#d3').trigger('click');
alert('after ');
});
$('#d2, #d3').click(function() {
alert('clicked ' +this.id);
});
Here are Opera's suggestions for dealing with timing
Don't have long-running scripts.
Don't use synchronous XMLHttpRequests.
Don't let scripts initiated from different frames manipulate the same global state.
Don't use alert boxes for debugging, as they might change the logic of the program completely.

Well, that actually depends on what do you do in your handler and how do you define 1st handler ended moment?
For example, if you're doing only sync operations in eventHandler1 then you're sure that eventHandler2 won't get triggered before eventHandler1 finishes. the reason is javascript being single threaded.
But, imagine scenario like this:
click on button1 triggers eventHandler1 which actually makes ajax request. in that scenario, what do you actually consider as 'end of eventHandler1'? if it is the moment when ajax request returns then certainly eventHandler2 will start (and possible end) execution before eventHandler1 finishes.
To put it short: whenever you do sync-only operations > the order is guaranteed.
Added from comments:
http://www.w3.org/TR/DOM-Level-3-Events/#sync-async for example, it says: " Each event in this virtual queue must be delayed until the previous event has completed its propagation behavior, or been canceled."
Well, now we're back to the question 'what type of events are we talking about'? As mentioned before: if it's async events then sure the order is not guaranteed. But the original dilemma was about click event and that one is not async but sync. And for sync events documentation clearly states: Events which are synchronous ("sync events") must be treated as if they are in a virtual queue in a first-in-first-out model, ordered by sequence of temporal occurrence, with respect to other events, to changes in the DOM, and to user interaction.
yep, no guarantees. now add javascript being single-threaded into play and you can't get them executing at the same time. but yes, speaking of DOM strictly - there is no guarantee whatsoever which one will happen before.
just one more comment... you might have exactly the same DOM but accessed from Java multi-thread environment. What then?:) then you have to implement your own thread-safe async events handling because you're no more 'protected' by single thread environment as you have with javascript. So, the conclusion, as i see it is that DOM specs does require that sync events are fifo implemented. for async events execution depends on stack/thread implementation. in Javascript, that means that 2 handlers can't overlap but in Java e.g. doesn't have to mean.

Related

Simultaneous access to variable

I need to increment global variable from several callbacks (event handlers), which may fire simultaneously. Do I need to worry about simultaneous access to that variable? Is there any analog of Interlocked.Increment like in C#?
Is there any analog of Interlocked.Increment in JavaScript?
Yes, but you don't need it for your scenario.¹
I mean I need to increment global value from several different callbacks (event handlers), which may fire simultaneously.
They will never fire simultaneously. JavaScript on browsers runs only a single thread per global environment (the spec calls this a realm), sometimes sharing the same thread across multiple global environments. Even if the handlers' events fire simultaneously or all of the handlers respond to the same event, the calls to them are queued in a task queue (the JS spec calls it a job queue, HTML spec calls it a task queue), and that queue is processed one task/job at a time.
Do I need to worry about simultaneous access to that variable?
Not in your scenario, no.
¹ Just for detail: You only need it when sharing SharedArrayBuffer instances with multiple threads (on browsers, that would be via web workers). It's Atomics.add and operates on a typed array, which might be backed by a SharedArrayBuffer.
Any client-side JavaScript code is synchronous by default. Events are pushed onto an event queue and processed in a single-threaded event loop. Therefore, you don't need to be concerned with race conditions. Refer to e.g. https://medium.com/#kvosswinkel/is-javascript-synchronous-or-asynchronous-what-the-hell-is-a-promise-7aa9dd8f3bfb.
The only exception to this is when you start using web workers. In this case you may take a look at Atomics (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics), for example.

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.

How JS determine when to call Callback function?

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.

Race conditions with JavaScript event handling?

We understand that JavaScript is single threaded, but we want to confirm our understanding of asynchronous event handling in JavaScript. More importantly, we want to confirm we're not exposed to potential race conditions.
Conceptually, our mobile app works like this:
We invoke function foo when a mobile page is loaded.
At the end of foo, we use setTimeout to invoke foo again (with one second delay) if a counter is greater than 0. If the counter hits 0, we load a new page. The timeout is saved in a variable.
If a button is tapped, we invoke function do_tap and clear the timeout variable saved in step two (and do other stuff).
do_tap and foo both update the same page element, and we want to confirm that they wouldn't step on each other.
Questions:
Assume a tap occurs during the execution of foo. Will the browser queue do_tap to start executing after foo finishes? In other words, are we guaranteed that once foo starts, we can never see execution of foo and do_tap interleaved?
What if the tap occurs first? do_tap is guaranteed to complete before foo starts, right?
Except for web workers and cooperating frames or windows (which aren't being used here), Javascript is single threaded within a given window so there are never two threads of execution running at the same time in that window. As such, you don't ever have to worry about race conditions that might be a typical worry when using threads.
Under the covers, Javascript has an event queue. Your current thread of execution will run to completion and then when it completes, the javascript interpreter will check the event queue to see if there are more things to do. If so, it fires that event and starts up another thread of execution. Pretty much everything goes through that event queue (timers, key events, resize events, mouse events, etc...).
You can read more about it and see a bunch of relevant references in one of my other answers on this subject.
Event execution proceeds single-threaded until the event has been handled. Until that time, no other event loop will be initiated.
In other words, while a handler is running for some event, no other handler for any other event will interrupt it.
Thus the answer to both question 1 and question 2 is "Yes." (This is, of course, barring browser bugs, but if you take that into account you can't get very far. It's not like there are any synchronization primitives to fall back on. I say this only because there was a period of time during which Safari could fire a "DOMready" event in the middle of running another "DOMready" event handler. That was, however, quite clearly a bug.)
As long as the first thing Do_tap() does is clearTimeout there will be no chance for foo to be running during the execution of Do_tap(). However, if an asynchronous process was initiated in foo() such a database request then there could be a potential wait to access the database in Do_tap() as foo() finishes its request, and if foo() has a callback function that could theoretically be called after Do_tap() was done executing.
I didn't catch anyone else saying this, but I think the answer to #2 is that different browser implementations can and do differ in subtle ways as to which queued events are processed first. No, there is no possibility of interleaving, but whether setTimeout(func, 0) or a mouse event is handled first is not guaranteed by the language spec and in practice can matter. Whereas setTimeout(func, 100) is guaranteed to be processed later than pending events received during the currently handled event.
Just saying.

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