async in script doesn't act like multithreading but similar to defer - javascript

I theoretically know the differences between async and defer used in <script> tag.
async: The script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing).
defer: The script is executed when the page has finished parsing.
But can't understand the mechanism they follow.
I have the following 2 files-1.js and 1.html.
1.js
alert('Running external JS');
1.html
<html>
<body>
<script src="1.js" async></script>
<script>
for(var i=0;i<5;i++)
{
alert('HTML code1');
}
</script>
<script>
for(var i=0;i<5;i++)
{
alert('HTML code2');
}
</script>
</body>
</html>
The html file executes s.t. all the alert statements execute first and then at last the script 1.js executes i.e. it acts similarly as when I use defer in place of async in the <script>-tag.
As per my expectation as the external script is much smaller than the code in the HTML itself it should have been triggered anywhere in between the alert statements in the HTML document as I am using async but acting similar to the effect of using defer.
Please explain what happened here also please correct me if I am wrong.

Related

Registering an async javascript, declarative (static) vs dynamic

Is there any difference in declaring my async javascript statically vs dynamically?
static
<html>
<head>
...
</head>
<body>
...
<div id='my-script-needs-me'></div>
<script type="text/javascript" src="https://foo.bar/myscript.js" async>
</script>
...
</body>
</html>
dynamic
<html>
<head>
...
</head>
<body>
...
<div id='my-script-needs-me'></div>
<script type="text/javascript">
var myScript = document.createElement("script");
myScript.src = 'https://foo.bar/myscript.js';
myScript.async = !0;
myScript.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(myScript);
</script>
...
</body>
</html>
I noticed that declaring a script statically let a browser detect it earlier and preload (chrome + firefox).
My goal is to load a javascript in async way in order not to block HTML rendering and other scripts execution. Sametime, I want it to be executed as soon as it's downloaded, having in mind that it requires one element to be in the DOM already. Once downloaded the script is executed and it accesses the my-script-needs-me div. One limitation, I cannot change the script itself.
supports async parameters allowing to make this call asynchronous.
The second way you described allows you to have the url as a parameter and bind it.
It allows too the use of a callback to do some stuff when your script is loaded.
let scriptElement = document.createElement('script');
let url = `https://maps.googleapis.com/maps/api/js?key=${apiKey}`;//&libraries=geometry
scriptElement.src = url;
//Chargement de l'API Google
scriptElement.onload = () => {
//API chargée, on peut lancer l'initialisation du composant
this._initializeMap();
};
I used this to load Google Maps API, it's not directly in the HTML, so i can modify the URL when my page loads. And when the API is loaded, I an launch treatments that need this API.
you can use defer for that instead of async.
your script will execute right after html be parsed.
Static
<html>
<head>
...
</head>
<body>
...
<div id='my-script-needs-me'></div>
<script type="text/javascript" src="https://foo.bar/myscript.js" async>
</script>
...
</body>
</html>
As you know, HTML is parsed top-bottom. So, if it placed within body tag, then as soon as parsed, if it is an IIFE or the file myscript.js contains a function call, it will execute immediately.
So, inside, body, put it the script at the bottom will help you to execute it after the div has loaded.
But we can't ensure because of caching.
If the browser cache the script and if it is an IIFE or contains a function call, we can't predict the behaviour.
Dynamic
In dynamic also, it depends on the order.
<html>
<head>
...
</head>
<body>
...
<div id='my-script-needs-me'></div>
<script type="text/javascript">
var myScript = document.createElement("script");
myScript.src = 'https://foo.bar/myscript.js';
myScript.async = !0;
myScript.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(myScript);
</script>
...
</body>
</html>
In both cases, it will render after HTML contents.
The best way to ensure it loads only after all contents are loaded is
Giving an eventListener on Window.
Check the code below
<html>
<head>
...
</head>
<body>
...
<div id='my-script-needs-me'></div>
<script type="text/javascript">
function load(){
var myScript = document.createElement("script");
myScript.src = 'https://foo.bar/myscript.js';
myScript.async = !0;
myScript.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(myScript);
}
window.addEventListener("DOMContentLoaded",load);
</script>
...
</body>
</html>
Check this line window.addEventListener("DOMContentLoaded",load);.
The DOMContentLoaded is similar to jQuery's $(document).ready(). It will trigger the callback function when the HTML is properly loaded. So, you don't have to check for the existence of the HTML Element.
From what I've learned it's better to go with static way to declare an async script (in my particular scenario) than dynamic. Here some of why(s):
static async script declaration is detected by a browser and kicked off right away (at the very top of the page processing);
(deferred from #1) a browser puts the script request earlier in requests queue and if you have enough (30-40 requests per page load) it could be crucial to be in first 10 requests, not at the position 30-40;
adding a script dynamically to the head from the body doesn't introduce any performance advantage against the static declaration as long as whole head is already processed and it won't delay execution of the statically declared script;
at the moment when we reach the script declaration, static will work instantly because it's already pre-loaded and ready to be executed (in most cases, async is crucial here) while the dynamic script declaration will just kick off the request to download the script and only after then execute it;
I hope my thoughts will help someone as well.

What is the execution order when both sync and async script tags are used?

Tell me if I am wrong. The JavaScript code execute as a single thread.
The execution of below JavaScript code will be A,B and C, sequentially right.
<script src="A"> .... </script>
<script src="B"> .... </script>
<script src="C"> .... </script>
The execution of below code will depend upon the code and the time given to each scripts means first 'A' will start to execute (or 'B', don't know), the execution of 'A' will stop because the time given to it is complete than the others will get the same chance say 'B' , than 'C' and than 'A' again resume and the cycle goes on till the execution of each scripts done.
<script async src="A"> .... </script>
<script async src="B"> .... </script>
<script async src="C"> .... </script>
But what happen when there are both synchronous and asynchronous scripts occur like below.
<script sync src="A"> .... </script>
<script async src="B"> .... </script>
<script sync src="C"> .... </script>
<script sync src="D"> .... </script>
<script async src="E"> .... </script>
The async attribute merely means that the script will be downloaded sometime later and therefore will start executing sometime later. <script> tags without that attribute will be downloaded immediately and block the rest of the page until the download and execution is finished.
async does not mean that once the script runs, it may get interrupted at any time and another script may start to run. That is cooperative multitasking/CPU scheduling and is absolutely not what happens here. The first async script which happens to complete downloading will run, until it is done, at which point the next script will start to run if there's any.
So, yes, with async you do not know when your script will start executing, but once it does, it is the only thing running until it relinquishes that power (meaning the script and/or function exits).
I haven't seen anywhere the sync attribute that we can use. As far as I know there's only the way we can use the attribute is async.
But for your query, you should be using without attribute and this will be synchronous automatically:
<script src="A"> .... </script>
<script async src="B"> .... </script>
<script src="C"> .... </script>
<script src="D"> .... </script>
<script async src="E"> .... </script>
And now to answer your question,
Asynchronous scripts are loaded in the background while synchronous scripts are loaded in order and affect html and css also.
So, we can not guarantee that using like your exammple order of scripts with synchronous and asynchronous scripts because asynchronous scripts loaded in the background and may be loaded before or after the other synchronous scripts.

JavaScript code in library.js executing at onLoad event

In all the research I've done, I am under the impression function calls in 'scr' files is not executed until called in the of the DOM. But this does not seem to be true.
My example:
<title id="pageTitle">Investment(s)
</title>
<script type="text/javascript" src="../javascript/library.js">
</script>
<script type="text/javascript" src="../javascript/investment.js">
</script>
...any function in either 'src' file with an alert() statement, shows up at onLoad(). Is this normal?
Thanks for any help you can offer.
<script> tags cause the browser to stop what it is doing and begin downloading/executing the script immediately. They do not wait for the dom to finish loading before they run. Read more.

Synchronous external JS loading with zombie.js

The problem:
I'm using zombie.js to test my client-side javascript, but I am running into a problem. Zombie.js does not provide synchronous <script> tag execution, and, in fact seems to not execute external JS files at all. A basic test confirms this:
<script type="text/javascript" src="test1.js"></script>
<script type="text/javascript" src="test2.js"></script>
<script type="text/javascript" src="test3.js"></script>
<script type="text/javascript">
console.log("Inline javascript.");
</script>
Each test#.js contains a single line: console.log("TEST#.JS");
When I render this in a regular browser, the console displays the expected:
TEST1.JS
TEST2.JS
TEST3.JS
Inline javascript.
But when I run it with zombie.js, I only see a single line Inline javascript.
Here's what I have tried to get around the issue:
using document.createElement to dynamically append a script tag to the document
using document.write to add the script block into the html
using a setTimeout on console.log("Inline javascript") in combination with 1 and 2 to give the test scripts some time to load.
Is there any way to resolve this issue, besides placing the JS code from all my external JS files into a huge <script> block?
Are you sure the browser object has the "runScripts" option set to true? If not you can use the following syntax:
browser.visit('... your page url ...', { runScripts: true }, function (e, b) {
console.log('executing callback');
});

JavaScript functions in external scripts

I'm learning JavaScript for a project, but I am stuck at the very beginning. I boiled it down, to the function in my script not being defined, but as near as I can tell it is defined.
I have a script: "script.js" with the function display result.
function displayResult()
{
document.write("hello world");
}
in the header of index.html I have this line
<script type="text/javascript" href="script.js"></script>
I have this line later
<body onload="displayResult()">
I have no idea why my function will not call. I would appreciate the help.
<script type="text/javascript" href="script.js"></script>
Should be:
<script type="text/javascript" src="script.js"></script>
there is no href attribute to a script block, its included from an external source through the src attribute.
BTW, calling document.write after the document has finished loading will first clear the entire content of the document, then replace it with whatever you pass to the call (in this case, 'hello world', which is not a valid HTML or XML document).

Categories

Resources