I know PHP, server-side scripts, run first and output the html to the browser, then javascript is executed. However, I am trying to get a feel for how the javascript is executed and can't quite figure it out.
Is Javascript executed top-down and is consistent with this top-down execution? I am dynamically creating javascript in PHP which is triggered by events in my webpage's original javascript.
Will created JS execute exactly where I put it or will it fire before? after?
Thanks
Well javascript will execute one line after the another. But also javascript is the event based language hence there will be certain part of the code which will be based on events and will execute only when the events take place.
For eg: click,hover etc events
or functions like setTimeout and setInterval
these function will execute only when the particular events takes place
JavaScript is executed by the clients browser and is parsed in conjunction with the HTML and CSS, whichever comes first.
Is Javascript executed top-down and is consistent with this top-down execution?
Yes
Will created JS execute exactly where I put it or will it fire before? after?
JavaScript inserted into the DOM will be parsed/executed immediately.
Javascript is read and run by the user's web browser whereas PHP is run server-side. The PHP code is compiled, HTML (with Javascript) is served, the user's browser reads the HTML and Javascript.
Is Javascript executed top-down and is consistent with this top-down execution?
Yes
With a lesser-known exception:
Function statements will be executed before any other statements (but not function operators).
So this would run fine:
f();
function f() { console.log("a"); }
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)
I'm loading some javascript code via ajax (as a <script> block inside an html string), and I'm using jquery.html() to inject that payload into a <div>. The jquery.html() method automatically evals injected <script> elements.
I would like to wait for the code in the <script> block to complete execution before releasing execution back to the main event loop. Even if the <script> contains callbacks, like an $.ajax().done() or setInterval(). Even if it causes an infinite loop, and even if it blocks any other events from being processed for a very long time.
Is this possible? I'm just wondering if there's some kind of synchronization-wrapper browser-supported utility in Javascript. My hunch is no, since this seems contrary to the single event-loop nature of Javascript, but I thought I'd check :) Ultimately, my goal is to insert custom javascript into the page upon a specific user action, and guarantee that the code will be executed in its entirety.
Note that I don't need to use jquery.html() or <script> injection, that's just my starting point. Maybe the best I can do is tell the client to invoke a specific pre-defined callback function when their code is finished, and make sure I don't change the window until this function is invoked?
You cannot "wait for the code in the block to complete execution before releasing execution back to the main event loop" in Javascript. That simply cannot be done.
Done right, you could insert the script tags with onload handlers so you would be notified (via a callback) when those scripts had finished loading and finished their synchronous execution (but not their async execution).
If you wanted to know when async execution in those scripts would be done, you would have to build something into those scripts to notify you when they were done.
If you're going to use jQuery's .html() to do script tag injection you lose a lot of control over this process and it becomes a hacking project to try to figure out what you can do from outside the process.
In all cases, you cannot prevent the continuing execution of the main event loop of javascript while waiting for this all to finish.
Is it possible to execute setTimeout() or setInterval() synchronously so that further execution that depends on its callback will not cause a not defined error?
intv = window.setInterval(function() {
// do some stuff
doSomeStuff();
// kill interval when stuff is done
if (stuffIsDone)
window.clearInterval(intv);
}, 10);
// dependent on "stuff" being done
// I want this to execute only after intv is cleared
doMoreStuff();
I don't want to put every consecutive call inside of a timeout to check if (typeof someStuff != 'undefined')
Yes, I do understand that this will cause a delay in loading and possible the UI. The intervals will be extremely small and inconsequential.
EDIT... Alright, what I'm ultimately trying to do is dynamically add a number of javascript files dynamically, by only including a single javascript file.
ie.:
// auto include all javascript files
<script language="javascript" type="text/javascript" src="include.js"></script>
This works by requesting the JSON list of javascript files from the server via AJAX. It loops through the list and adds the scripts dynamically to the DOM.
The catch:
If I add the scripts using setInterval, they are sometimes added after the onLoad event fires, depending on the current computational load of the machine executing the code. So, when I call functions from one of the files onLoad, it causes an error (because at the time of execution, the function didn't exist)
If I add the scripts inside of a while loop, the dynamically added scripts to do not execute and the internal references between the scripts are invalid and error out.
So, the question really is: without using setInterval and typeof on every call, how do I dynamically add scripts reliably so that dependent code doesn't attempt to execute before the depended-upon scripts are loaded?
Take a look at Refactoring setInterval-based Polling and consider converting your setInterval to a setTimeout and use a Promise to execute doMoreStuff() after stuffIsDone is true.
That article is from 2013, so consider Promises/A+ (using a polyfill for ES6-style Promises for older browsers) instead of jQuery's or Underscore's implementation.
You can run a while loop and keep track of the system time if you want to block the JavaScript thread for a fixed period of time.
For example:
var startMillis = Date.now();
while (Date.now() - startMillis < 10);
Note that no other code will run during this period. JavaScript is single threaded.
Don't know exactly what you're trying to do, but this seems a little strange :)
I'm currently experimenting with embedding V8 in a project of mine. Since I use libev for listening to sockets and events and want to be able to script events with JS I would want to be able to just run v8 for a short while and then jump back to C++ to check for events and such and then go back to running JS-code. Since I haven't done much script embedding earlier I'm sure there are some clever way that this usually is done in so all ideas are appreciated.
The cleanest way I found of doing this is to create setTimeout and clearTimeout functions within JS. setTimeout creates a ev::Timer which has a callback that gets called after a certain amount of time. This makes it so that when you call a JS function you continue to execute that until it returns, but that function can set a number of timeouts which aren't called until after you exit the current JS and there hasn't happened any other libev events during the execution, in that case those are handled first (in C++). The limitations of this method is that the coder who writes JS has to remember to not write functions that goes into eternal while-loops or similar. A loop is instead done like this:
function repeat() { setTimeout(repeat, 0); }
Does the code (e.g. functions) execute at the same time or does it follows the order in which it was written (top to bottom)? I know that order matters in HTML, what about JavaScript?
For instance, if there are two function calls one after the other, will they get executed simultaneously or one after the other even if they have nothing to do with each other?
It may seem as if Javascript functions are executing in an unpredictable order because the model for Javascript in a browser is event-driven. This means that a Javascript program typically attaches event handlers to DOM elements and these are triggered by user actions such as clicking or moving the pointer over an element. However, the script that sets up the event handlers runs as a traditional structured imperative program.
A further complication is that modern Javascript applications make extensive use of asynchronous functions. This means that a function call might return quickly but will have set in motion an action which completes at a later time. An obvious example is the sending of requests to a server in so-called AJAX applications. Typically the request function is passed a callback function which is called when the request completes. However the Javascript program will go on to the next statement without waiting for the completion of the request. This can be somewhat confusing if you aren't thinking clearly enough about what your program is actually doing.
Another example that you might sometimes encounter is the launching of animations in jQuery. These too work asynchronously and you can pass a callback function that runs after the animation completes. Once again this can be surprising sometimes if you expect the next statement to be executed after the animation completes rather than after it starts.
It occurs in the order it was written (with various exceptions). More specifically it's an imperative structured object-oriented prototype based scripting language :)
See Imperative Programming