I found an article in Events and timing in-depth, there is an example in this article:
function run() {
var div = document.getElementsByTagName('div')[0]
for(var i=0xA00000;i<0xFFFFFF;i++) {
div.style.backgroundColor = '#'+i.toString(16)
}
}
which says:
In most browsers, you see nothing until the script finishes, or until
the browser pauses it with a message that ‘a script is running too
long’.
which means I can't see animation while these code is executing.
But why?I don't quite understand this, is the code execute too fast? Or the render job is done after execute the code?
and why add a setTimeout could show the animate?
While the run() function is executing the browser doesn't update the page. It waits until the function has completed executing. However with setTimeout it runs in increments - The browser updates the page for/after each run.
The summary on the link in your question explains it well :
Most browsers use single thread for UI and JavaScript, which is
blocked by synchronous calls. So, JavaScript execution blocks the
rendering.
Events are processed asynchronously with the exception of DOM events.
The setTimeout(..,0) trick is very useful. It allows to:
Let the browser render current changes. Evade the “script is running
too long” warning. Change the execution flow. Opera is special in many
places when it comes to timeouts and threading.
Related
I'm a NodeJs developer that happens to have some web applications.
I'm very familiar with asynchronous code and how the event loop works. However I been facing a problem that I was unable to fix until I realized that asynchronous code may behave different when it is splitted across several script tags.
The situation was as follows
I had one script tag at the head section with some asynchronous code. Such code expected some function to exist. That function should be declared on the second script tag in a synchronous fashion, so at the time the async stuff completes that function should exist.
Te second script tag is 100% synchronous and at the middle of the code it created a function called boot.
Let me ilustrate it with some simplified code:
// <script>
somePromise()
.then( ()=> window.boot())
// </script>
// < ... some html code and body >
// <script>
window.boot = function (){}
// </script>
Since the promise callback should be executed asynchronously I expected it to go to the event loop and allow the rest of the synchronous code to execute.
On some browsers, this worked as I expect. When I say some browsers I mean browsers of different users on different computers, because the behavior varies even using the same browser brand and version. However, there were situations when the promise callback was executed before the second second script tag had a chance to start and raising an error.
How is this supposed to work on browsers ? Is each script tag executed until all its code is executed, even the asynchronous one ? If that is the case, why does it work for some other browsers?
Thanks in advance.
The HTML5 parser is not synchronous.
This is my own reworded extract of parts of HTML Parser Threading on MDN. Please refer to the original for formal treatment and heavy reading.
HTML between the script tag [pairs] is parsed by a nsHtml5StreamParser which executes off the main thread.
The parser runs its own event loop, and responds to requests from the main thread to perform onDataAvailable and OnStopRequest processing. Processing calls DoDataAvailable and doStopRequst respectively.
DoDataAvailable outputs small DOM tree operations, such as element creation into a queue processed in the main thread. The tree op queue is flushed to the main thread from time to time ** using a timer.**
After flushing the parser dispatches a runnable to the main thread to process tree additions. The runner (or executor) in the main thread calls nsHtml5TreeOpExecutor::RunFlushLoop().
A comment from #KarelG in this question says that network data is usually processed in 8Kb chunks. The question is well worth reading.
So the JavaScript Event Loop sometimes gets an opportunity to fulfill a promise and execute an onFulfilled handler before the second script element is parsed and executed - as you already discovered!
In summary it apppear that the vagaries of network retrieval of source code, asynchronous HTML parsing that uses a timer to instigate processing of tree building operations, and any further asynchronous operations that the tree builder may or may not invoke, all combine together to create a race condition.
The unpredictability of the failure branch of the race condition, when window.boot is not defined when called, is most likely due to the combined effects of browser brand, network speed, device utilization, length and type of HTML content, and HTML parser timing and timers.
The obvious conclusion is that code should not set up this kind of race condition in the first place. It is unsafe coding practice. Thankfully you can work around it.
Actually, promise is not suported in IE, so what you could do is to use some external libs, like bluebirdJS, or you could use a transpiler (babel or another one)
In my application, I have a submitSuccesscallback function, which will be triggered from my own JS library when submit was successful.
Within submitSuccesscallback, I am first displaying a loader and doing some initialization operations.
function submitSuccesscallback(){
showLoadingIndicator(); // has code a display loader
doSubmitSuccessOperations();// has code to do some app specific operations
}
here doSubmitSuccessOperations() is taking around 5 secs for complete execution.
Now my problem is above code does n't display loader (i.e ui changes from showLoadingIndicator()) upto 5 secs after I get the submitSuccesscallback().
If I change submitSuccesscallback() like below, I am able to see loader immediately after I trigger submitSuccesscallback().
function submitSuccesscallback(){
showLoadingIndicator(); // has code a display loader
setTimeout(doSubmitSuccessOperations, 1000);
}
Now what I would like to know is:
does setTimeout makes my doSubmitSuccessOperations() run in background?
I clearly sense that doSubmitSuccessOperations() is blocking UI operation, is there any concept of UI thread and background thread in JS?
Any other alternative for setTimeout above?
does setTimeout makes my doSubmitSuccessOperations() run in background?
No. JS is single-threaded. Code and rendering are in the same thread. That's why long-running operations block rendering.
What setTimeout does is set aside that operation until the engine can execute it (it doesn't halt running code) and is at least (and not exactly) after the delay you specified. Code that comes after it executes normally as if it were the next operation in the thread. That means the code inside setTimeout is already not in the same order it appears in your code.
I clearly sense that doSubmitSuccessOperations() is blocking UI operation, is there any concept of UI thread and background thread in JS?
Any other alternative for setTimeout above?
Async programming is one, and timers (setTimeout and friends) are the most available. In other environments, IE has setImmediate, and Node has process.nextTick. There's also WebWorkers, which are closer to real threads. If you have a server, you can use AJAX (which is also a form of async operation) to call a server and let it do the operation for you.
Here's a video that explains how the event loop works. Somewhere in the middle of the video explains how setTimeout schedules your callbacks.
Basically, you have a JavaScript engine that is running your code in the browser. This engine has a call stack. It's a stack of all the functions that you queued for executing. There is also a thing called the event loop which is a queue that contain functions that are queued there as a side effect of some event. When the call stack is empty, the function that is put on the top of the event loop is pushed in the call stack and get executed. This call stack is "inside" your UI thread.
When you call setTimeout(doSubmitSuccessOperations, 1000); the doSubmitSuccessOperations is added to the event loop 1 second after this line of code is executed. When all your UI logic is executed(showing spinners, moving texts, animations, etc.), the call stack will be empty. Then doSubmitSuccessOperations will be popped out of the event loop and pushed inside the call stack. This is when the function gets executed.
So, no, setTimeout does not make doSubmitSuccessOperations run in the background. It just make it run after your UI logic.
There is a concept for background thread and it's called a service worker. But you can't do UI operations inside it.
1) does setTimeout makes my doSubmitSuccessOperations() run in background? - No
2) I clearly sense that doSubmitSuccessOperations() is blocking UI operation, is there any concept of UI thread and background thread in JS? - No
3) Any other alternative for setTimeout above? - you can try and put 0 in the timeout, this way the engine will try to execute the function in the first available spot.
All of your queries explained in other answer for your third query you can use callback pattern to show loading image it will work you can try
Instead of this
function submitSuccesscallback(){
showLoadingIndicator(); // has code a display loader
doSubmitSuccessOperations();// has code to do some app specific operations
}
something like
submitSuccesscallback(function(){
showLoadingIndicator(function(){
doSubmitSuccessOperations()
})
})
And your other function must handle callback something like
function showLoadingIndicator(callback){
// your code to display loading image
$('loadingimage').show(0,'', function(){
callback();
});
}
function submitSuccesscallback(callback){
// your code must be sync here
// if asynchrony than call callback in .success function
//at last(if no asyn operation)
callback()
}
I'm using a graph visualization library in $(document).ready() and it seems to block UI. I was expecting $(document).ready() to execute in a separate thread.
Does any one know about the details? Maybe I should use setTimeout to run the code asynchronously?
Edit:
The term "asynchronous" and "separate thread" is misleading in JavaScript. I'm not an expert of JavaScript and I can't find more accurate term. Please see the answers for clarification.
With the exception of Web Workers (which do not have direct access to DOM), JavaScript runs in a single thread. $(document).ready() is asynchronous in the sense that the callback you pass to it may fire right away or sometime later when the DOM is loaded, but when its callback actually runs, it is the only thing that the JS runtime is processing.
A long-running for loop, for instance, will block the UI thread regardless of whether it is in a ready callback, an event handler, an async XHR's success callback, etc. The only way to prevent it from blocking the thread would be to break it up into several loops by scheduling later chunks using setTimeout.
There is no separate thread in JavaScript. All JavaScript is executing in a single thread; UI updates are executing in the same thread. If your JavaScript is busy, UI updates do not happen. "asynchronous" is a bit of a misleading term here; it means that execution of a function will be deferred (but still in a single thread).
Basically, a browser has an execution queue. All event handlers are put into the execution queue when they are triggered; as are timeout functions. When any function with no callers exits, the next function in the queue is executed. UI updates are also in the same queue.
So when you do $(document).ready(fn), it (in simple terms; jQuery makes it a bit complex, especially for older browsers) will attach a handler. This handler will get triggered by the browser when all the content is loaded, which will put it onto the execution queue. When it is its turn, it will execute; any UI updates it performs will be painted when the handler exits.
--
*) There is an exception to the single-thread rule: web workers. Each web worker runs in its own thread, but they are very limited as to what they can do; basically, computation only (they can't access UI at all).
Asynchronous doesn't mean multithread. Javascript is event based, functions will be called when something happens (an event occurs). The event listening function is not executed on a separate thread, its just planned to be executed later.
But there one old technique to emulate multithread without the browser support for Web Workers. It's splitting up one whole task into deferring small tasks.
For example, you write this which will cause blocking:
for (var i = 0; i < 10000000; i++) {
// do something very slow
}
Turn it to this, and it will execute parallel, almost like multithreaded.
(function step(i) {
if (i < 10000000) {
// do something very slow
setTimeout(function() {step(i + 1)}, 1);
}
})(0);
Edit: I just realized that this will cause memory problem, because in each step closure we are referencing the previous step, making it impossible for the GC to clean up memory. To overcome this, put i out of the arguments, and change it like this (I'm wrapping the whole thing with a function, so that i can not be changed mistakenly outside):
(function() {
var i = 0;
(function step() {
if (i < 10000000) {
// do something very slow
i++;
setTimeout(step, 1);
}
})();
})();
I have been under the impression for that JavaScript was always asynchronous. However, I have learned that there are situations where it is not (ie DOM manipulations). Is there a good reference anywhere about when it will be synchronous and when it will be asynchronous? Does jQuery affect this at all?
JavaScript is always synchronous and single-threaded. If you're executing a JavaScript block of code on a page then no other JavaScript on that page will currently be executed.
JavaScript is only asynchronous in the sense that it can make, for example, Ajax calls. The Ajax call will stop executing and other code will be able to execute until the call returns (successfully or otherwise), at which point the callback will run synchronously. No other code will be running at this point. It won't interrupt any other code that's currently running.
JavaScript timers operate with this same kind of callback.
Describing JavaScript as asynchronous is perhaps misleading. It's more accurate to say that JavaScript is synchronous and single-threaded with various callback mechanisms.
jQuery has an option on Ajax calls to make them synchronously (with the async: false option). Beginners might be tempted to use this incorrectly because it allows a more traditional programming model that one might be more used to. The reason it's problematic is that this option will block all JavaScript on the page until it finishes, including all event handlers and timers.
JavaScript is single threaded and has a synchronous execution model. Single threaded means that one command is being executed at a time. Synchronous means one at a time i.e. one line of code is being executed at time in order the code appears. So in JavaScript one thing is happening at a time.
Execution Context
The JavaScript engine interacts with other engines in the browser.
In the JavaScript execution stack there is global context at the bottom and then when we invoke functions the JavaScript engine creates new execution contexts for respective functions. When the called function exits its execution context is popped from the stack, and then next execution context is popped and so on...
For example
function abc()
{
console.log('abc');
}
function xyz()
{
abc()
console.log('xyz');
}
var one = 1;
xyz();
In the above code a global execution context will be created and in this context var one will be stored and its value will be 1... when the xyz() invocation is called then a new execution context will be created and if we had defined any variable in xyz function those variables would be stored in the execution context of xyz(). In the xyz function we invoke abc() and then the abc() execution context is created and put on the execution stack... Now when abc() finishes its context is popped from stack, then the xyz() context is popped from stack and then global context will be popped...
Now about asynchronous callbacks; asynchronous means more than one at a time.
Just like the execution stack there is the Event Queue. When we want to be notified about some event in the JavaScript engine we can listen to that event, and that event is placed on the queue. For example an Ajax request event, or HTTP request event.
Whenever the execution stack is empty, like shown in above code example, the JavaScript engine periodically looks at the event queue and sees if there is any event to be notified about. For example in the queue there were two events, an ajax request and a HTTP request. It also looks to see if there is a function which needs to be run on that event trigger... So the JavaScript engine is notified about the event and knows the respective function to execute on that event... So the JavaScript engine invokes the handler function, in the example case, e.g. AjaxHandler() will be invoked and like always when a function is invoked its execution context is placed on the execution context and now the function execution finishes and the event ajax request is also removed from the event queue... When AjaxHandler() finishes the execution stack is empty so the engine again looks at the event queue and runs the event handler function of HTTP request which was next in queue. It is important to remember that the event queue is processed only when execution stack is empty.
For example see the code below explaining the execution stack and event queue handling by Javascript engine.
function waitfunction() {
var a = 5000 + new Date().getTime();
while (new Date() < a){}
console.log('waitfunction() context will be popped after this line');
}
function clickHandler() {
console.log('click event handler...');
}
document.addEventListener('click', clickHandler);
waitfunction(); //a new context for this function is created and placed on the execution stack
console.log('global context will be popped after this line');
And
<html>
<head>
</head>
<body>
<script src="program.js"></script>
</body>
</html>
Now run the webpage and click on the page, and see the output on console. The output will be
waitfunction() context will be popped after this line
global context will be emptied after this line
click event handler...
The JavaScript engine is running the code synchronously as explained in the execution context portion, the browser is asynchronously putting things in event queue. So the functions which take a very long time to complete can interrupt event handling. Things happening in a browser like events are handled this way by JavaScript, if there is a listener supposed to run, the engine will run it when the execution stack is empty. And events are processed in the order they happen, so the asynchronous part is about what is happening outside the engine i.e. what should the engine do when those outside events happen.
So JavaScript is always synchronous.
JavaScript is single-threaded, and all the time you work on a normal synchronous code-flow execution.
Good examples of the asynchronous behavior that JavaScript can have are events (user interaction, Ajax request results, etc) and timers, basically actions that might happen at any time.
I would recommend you to give a look to the following article:
How JavaScript Timers Work
That article will help you to understand the single-threaded nature of JavaScript and how timers work internally and how asynchronous JavaScript execution works.
To someone who really understands how JS works this question might seem off, however most people who use JS do not have such a deep level of insight (and don't necessarily need it) and to them this is a fairly confusing point, I will try to answer from that perspective.
JS is synchronous in the way its code is executed. each line only runs after the line before it has completed and if that line calls a function after that is complete etc...
The main point of confusion arises from the fact that your browser is able to tell JS to execute more code at anytime (similar to how you can execute more JS code on a page from the console). As an example JS has Callback functions who's purpose is to allow JS to BEHAVE asynchronously so further parts of JS can run while waiting for a JS function that has been executed (I.E. a GET call) to return back an answer, JS will continue to run until the browser has an answer at that point the event loop (browser) will execute the JS code that calls the callback function.
Since the event loop (browser) can input more JS to be executed at any point in that sense JS is asynchronous (the primary things that will cause a browser to input JS code are timeouts, callbacks and events)
I hope this is clear enough to be helpful to somebody.
Definition
The term "asynchronous" can be used in slightly different meanings, resulting in seemingly conflicting answers here, while they are actually not. Wikipedia on Asynchrony has this definition:
Asynchrony, in computer programming, refers to the occurrence of events independent of the main program flow and ways to deal with such events. These may be "outside" events such as the arrival of signals, or actions instigated by a program that take place concurrently with program execution, without the program blocking to wait for results.
non-JavaScript code can queue such "outside" events to some of JavaScript's event queues. But that is as far as it goes.
No Preemption
There is no external interruption of running JavaScript code in order to execute some other JavaScript code in your script. Pieces of JavaScript are executed one after the other, and the order is determined by the order of events in each event queue, and the priority of those queues.
For instance, you can be absolutely sure that no other JavaScript (in the same script) will ever execute while the following piece of code is executing:
let a = [1, 4, 15, 7, 2];
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum += a[i];
}
In other words, there is no preemption in JavaScript. Whatever may be in the event queues, the processing of those events will have to wait until such piece of code has ran to completion. The EcmaScript specification says in section 8.4 Jobs and Jobs Queues:
Execution of a Job can be initiated only when there is no running execution context and the execution context stack is empty.
Examples of Asynchrony
As others have already written, there are several situations where asynchrony comes into play in JavaScript, and it always involves an event queue, which can only result in JavaScript execution when there is no other JavaScript code executing:
setTimeout(): the agent (e.g. browser) will put an event in an event queue when the timeout has expired. The monitoring of the time and the placing of the event in the queue happens by non-JavaScript code, and so you could imagine this happens in parallel with the potential execution of some JavaScript code. But the callback provided to setTimeout can only execute when the currently executing JavaScript code has ran to completion and the appropriate event queue is being read.
fetch(): the agent will use OS functions to perform an HTTP request and monitor for any incoming response. Again, this non-JavaScript task may run in parallel with some JavaScript code that is still executing. But the promise resolution procedure, that will resolve the promise returned by fetch(), can only execute when the currently executing JavaScript has ran to completion.
requestAnimationFrame(): the browser's rendering engine (non-JavaScript) will place an event in the JavaScript queue when it is ready to perform a paint operation. When JavaScript event is processed the callback function is executed.
queueMicrotask(): immediately places an event in the microtask queue. The callback will be executed when the call stack is empty and that event is consumed.
There are many more examples, but all these functions are provided by the host environment, not by core EcmaScript. With core EcmaScript you can synchronously place an event in a Promise Job Queue with Promise.resolve().
Language Constructs
EcmaScript provides several language constructs to support the asynchrony pattern, such as yield, async, await. But let there be no mistake: no JavaScript code will be interrupted by an external event. The "interruption" that yield and await seem to provide is just a controlled, predefined way of returning from a function call and restoring its execution context later on, either by JS code (in the case of yield), or the event queue (in the case of await).
DOM event handling
When JavaScript code accesses the DOM API, this may in some cases make the DOM API trigger one or more synchronous notifications. And if your code has an event handler listening to that, it will be called.
This may come across as pre-emptive concurrency, but it is not: it is the JavaScript code that initiates the API call, and thus controls that the API can do some stuff, but this is just like a function call: once your event handler(s) return(s), the DOM API will eventually also return, and the original JavaScript code will continue after the API call it made.
In other cases the DOM API will just dispatch an event in the appropriate event queue, and JavaScript will pick it up once the call stack has been emptied.
See synchronous and asynchronous events
"I have been under the impression for that JavaScript was always
asynchronous"
You can use JavaScript in a synchronous way, or an asynchronous way. In fact JavaScript has really good asynchronous support. For example I might have code that requires a database request. I can then run other code, not dependent on that request, while I wait for that request to complete. This asynchronous coding is supported with promises, async/await, etc. But if you don't need a nice way to handle long waits then just use JS synchronously.
What do we mean by 'asynchronous'. Well it does not mean multi-threaded, but rather describes a non-dependent relationship. Check out this image from this popular answer:
A-Start ------------------------------------------ A-End
| B-Start -----------------------------------------|--- B-End
| | C-Start ------------------- C-End | |
| | | | | |
V V V V V V
1 thread->|<-A-|<--B---|<-C-|-A-|-C-|--A--|-B-|--C-->|---A---->|--B-->|
We see that a single threaded application can have async behavior. The work in function A is not dependent on function B completing, and so while function A began before function B, function A is able to complete at a later time and on the same thread.
So, just because JavaScript executes one command at a time, on a single thread, it does not then follow that JavaScript can only be used as a synchronous language.
"Is there a good reference anywhere about when it will be synchronous and when it will be asynchronous"
I'm wondering if this is the heart of your question. I take it that you mean how do you know if some code you are calling is async or sync. That is, will the rest of your code run off and do something while you wait for some result? Your first check should be the documentation for whichever library you are using. Node methods, for example, have clear names like readFileSync. If the documentation is no good there is a lot of help here on SO. EG:
How to know if a function is async?
In javascript, is there any different between these two:
// call MyFunction normal way
MyFunction();
// call MyFunction with setTimeout to 0 //
window.setTimeout('MyFunction()', 0);
The reason I asked was because recently came across the situation where the code only works if I use setTimeout(0) to call the function.
To my understanding, setTimeout(0) is exactly same as calling a function directly because you dont set any delay. But from what I see how it works in the code, setTimeout(0) seems to get executed last.
Can someone clarify exactly how setTimeout(0) really get called in order of the rest of other function call?
setTimeout() always causes the block of JavaScript to be queued for execution. It is a matter of when it will be executed, which is decided by the delay provided.
Calling setTimeout() with a delay of 0, will result in the JavaScript interpreter realizing that it is currently busy (executing the current function), and the interpreter will schedule the script block to be executed once the current call stack is empty (unless there are other script blocks that are also queued up).
It could take a long time for the call stack to become empty, which is why you are seeing a delay in execution. This is primarily due to the single-threaded nature of JavaScript in a single window context.
For the sake of completeness, MyFunction() will immediately execute the function. There will be no queuing involved.
PS: John Resig has some useful notes on how the JavaScript timing mechanism works.
PPS: The reason why your code "seems to work" only when you use setTimeout(fn(),0), is because browsers could update the DOM only when the current call stack is complete. Therefore, the next JavaScript block would recognize the DOM changes, which is quite possible in your case. A setTimeout() callback always creates a new call stack.
I would guess that the timeout only starts when the page is fully loaded, whereas just a plain 'MyFunction()' will execute as soon as it's processed.
The timer will try to execute once your current thread is done. This depends on where you call the window.setTimeout(). If it is in a javascript tag, but not inside a function, then it will be called once the end of the javascript tag is reached. For example:
<html>
<script type="text/javascript">
setTimeout(function(){alert("hello")},0);
var d=Number(new Date())+1000;
while(Number(new Date())<d){
}
alert("hi");
</script>
</html>
If you call the setTimeout inside a function that results from an event occuring, for example onload, then it will wait until the event handler function returns:
<html>
<script type="text/javascript">
document.addEventListener("mousedown",function(){
setTimeout(function(){alert("hello")},0);
var d=Number(new Date())+1000;
while(Number(new Date())<d){
}
alert("hi");
}, true);
</script>
</html>
It is impossible to make one thread in JavaScript wait while another thread is running. Event listeners will wait until the current thread is done before they start running.
The only exception is Web Workers, but they run in a different file, and the only way to communicate between them is using event listeners, so while you can send a message while the other is working, it won't receive that message until it is done, or it manually checks for messages.