How to load 2 Javascript files async and run one after another? - javascript

I have such structure:
<script src="/Content/Scripts/1.js"></script>
<script async src="/Content/Scripts/2.js"></script>
I need to load both files async and run 2.js file after 1.js. How could I do it?
If I add async to 2.js they will run at random.

You could dynamically add your scripts, in that way they are loaded asynchronously by default.
To ensure an ordered execution you could mark them explicitly as not async.
Here is a minimum example:
<html>
<head>
<script>
[
'https://code.jquery.com/jquery-1.11.3.min.js',
'1.js'
].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
</script>
</head>
<body>
</body>
</html>
The File 1.js contains jquery code:
$("body").append("<div>It works</div>");
In this example the files are loaded asynchrounously but keep the specified order. For further reading you can have a look at: http://www.html5rocks.com/en/tutorials/speed/script-loading/

One approach would be to to load the first file(1.js) asynchronously, and then dynamically add the second script as mentioned in the other answer, by making it to load asynchronously.
Load first file:
<script async src="/Content/Scripts/1.js"></script>
Then in the first file, include the following at the bottom,
var script = document.createElement('script');
script.src = "/Content/Scripts/2.js";
script.async = true;
document.head.appendChild(script);
Hope this helps :)

Regular asynchronous scripts doesn't support load ordering. BTW, ES2015 and above have the import syntax to asynchronously-load script files in order:
import x from "x.js";
import y from "y.js";
Or you can also use the programmatic API:
Promise.all([System.import("x.js"), System.import("y.js")]).then(() => {
// Do stuff once they've been already loaded...
});
If you want to use these features today, you should take a look at:
JSPM (which uses SystemJS as polyfill to ES2015 module loading).
Babel transpiler to compile ES2015 to ES 5.x.

Another way could be to use another attribute to store the second's source content
<script async src="/Content/Scripts/1.js"></script>
<script id="second" async data-src="/Content/Scripts/2.js"></script>
and inside the first script after you are finished with the dependent code between the 2 files(if any), write
var script = document.getElementById('second');
script.setAttribute("src",script.getAttribute("data-src"));
script.removeAttribute("data-src"); //Totally upto you if you want to remove it
Compared to the other solutions, this provides you more flexibility in placing the tag anywhere.

Going from "Abhishek singh" -s answer I created some snippet myself.
You can have as many js files to execute consecutively as you need.
html looks like this:
<title>Script execution sequence</title>
<body>
<script async data-ascript-id='2' data-src='second.js'></script>
<script async data-ascript-id='1' data-src='first.js'></script>
<script async src="pixel.js"></script>
</body>
pixel.js:
console.log("Pixel script executed");
var aon_scripts = document.querySelectorAll('[data-ascript-id]');
if(aon_scripts.length > 0){
var next_script = document.querySelectorAll('[data-ascript-id="1"]')[0];
console.log("pixel.js found next script");
next_script.setAttribute("src", next_script.getAttribute("data-src") );
}
first.js:
console.log("Next script executed");
var current_script = document.currentScript;
var this_script_data_id = current_script.getAttribute("data-ascript-id");
if(aon_scripts.length > parseInt(this_script_data_id) ){
console.log("There is more script");
var next_script = document.querySelectorAll('[data-ascript-id="'+
(parseInt(this_script_data_id) + 1) +'"]')[0];
next_script.setAttribute("src", next_script.getAttribute("data-src") );
}
else{
console.log("No more scripts to execute");
}
second.js and all from there will have the same code as first.js.
Output when I have first.js and second.js the same:
pixel.js: Pixel script executed
pixel.js:11 pixel.js found next script
first.js:1 Next script executed
first.js:9 There is more script
second.js:1 Next script executed
second.js:18 No more scripts to execute
If anyone wants a detailed explanation please let me know.

Related

JavaScript async & defer: run a script asynchronously

As far as I am aware, in the script element, the async attribute allows the script to download asynchronously (similar to images), while the defer causes the script to wait until the end before executing.
Suppose I have two scripts to include:
<script src="library.js"></script>
<script src="process.js"></script>
I would want them both to proceed asynchronously, and I would want process.js to wait until the end to start processing.
Is there a way to get the library.js script to run asynchronously?
Note
I see there appears to be some discrepancy between different online resources as to the actual role of the async attribute.
MDN & WhatWG suggest that it means that the script should execute asynchronously. Other online resources suggest that it should load asynchronously, but still blocks rendering when it is executed.
I found Sequential script loading in JavaScript which might help you:
(function(){
//three JS files that need to be loaded one after the other
var libs = [
'https://code.jquery.com/jquery-3.1.1.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/underscore.string/3.3.4/underscore.string.js'
];
var injectLibFromStack = function(){
if(libs.length > 0){
//grab the next item on the stack
var nextLib = libs.shift();
var headTag = document.getElementsByTagName('head')[0];
//create a script tag with this library
var scriptTag = document.createElement('script');
scriptTag.src = nextLib;
//when successful, inject the next script
scriptTag.onload = function(e){
console.log("---> loaded: " + e.target.src);
injectLibFromStack();
};
//append the script tag to the <head></head>
headTag.appendChild(scriptTag);
console.log("injecting: " + nextLib);
}
else return;
}
//start script injection
injectLibFromStack();
})();
Both defer and async affect when a script is executed, not when a script is downloaded. I think the confusion comes from the fact that some documentation is a bit sloppy with terms, and the term loaded is unclear as to whether it refers to the fetching of the resource, or the execution of it.
To get library.js to run asyncronously without waiting for the document to load, use async attribute, and to get process.js to wait until document has been parsed, use defer:
<script src="library.js" async></script>
<script src="process.js" defer></script>
Note that library.js is not guaranteed to run before process.js, although it probably will.

Load js Asynchronously But Execute Synchronously

The Scenario is that I have lots of js files. Different files are called depending on different platforms.
So I have a question as I want to load files Asynchronously. But the Execution of these files should be done synchronously. Currently I am doing this function call
function loadScriptJs(src) {
Console.log(' Call to file '+src);
var file = document.createElement('script'),
head = document.getElementsByTagName('head')[0];
file.type = 'text/javascript';
file.setAttribute("defer","defer");
file.setAttribute("src",src);
head.appendChild(file);
file.onload = function() {
console.log(src + " is loaded.");
};
}
Now I have a array which has a list of js files being called. I loop through the array and call this function for each src.
I have used document.ready function with in each of the js file. Here I have checked the dependencies of the files and made the sequence optimized. ie The dependent files are loaded later (come later in the array) and the more Parent like files come earlier.
Example:- If I have files A1,B2,C3,D4,E5 ..... like wise. My array is ['js/A1.js','js/B2.js','js/C3.js'...]. When I run this through the loop.
I get the consoles of 'Call to file [filename]' is the same sequence as in the array but consoles of '[filename] is loaded' are not coming in the intended sequence.
Yes I cannot control the loading as its over the internet. But I want to the execution to be synchronous. ie Begin all file execution when the last file completes loading.
Can anyone provide me any advice, suggestion or idea for it.
Dynamically inserted scripts may not adhere to the defer attribute. script tags have an async attribute. By default it's true. Explicitly set it to false.
file.setAttribute("async", "false");
or in plain HTML
<script type="text/javascript" async=false src="A1.js"></script>
You might also need to remove the document.ready method in each script and start the script's logic at the top level, appending each JS script to the bottom of the body tag instead of the header. If multiple scripts register for the ready event before it's fired you do not know what order they will be called in.

Make IE7 load javascript first then call function

IE7 gives the following error: 'myapp' is undefined
//home.html
<script type="application/x-javascript" src="//www.mysite.com/myjs.js"></script>
<script type="text/javascript" charset="utf-8">
new myapp.myfunc();
</script>
javascript file:
//myjs.js
myapp = {
myfunc : function(){
alert('hello world');
}
};
*I understand there are many ways to rewrite the code that is used on home.html, but I want to make this work without changing that. I found a working example with similar structure and no JS errors (IE7, IE6). https://google-developers.appspot.com/custom-search-ads/docs/sample
EDIT:
The < script > code will be given to external clients, so I want to keep it as simple as possible. See example link.
Occam's razor suggests that either IE/MSHTML does not support script elements with type="application/x-javascript". That might have to do with the fact that application/x-javascript is not a registered MIME media type, nor was it ever necessary.
Or it has to do with the fact that //www.mysite.example.com/myjs.js is not a supported URI-reference in that environment. Use fully-qualified URIs like http://www.mysite.example.com/myjs.js instead. (And please use the registered example domains for examples.)
You should also declare identifiers that you intend to use as variables:
var myapp = {
…
};
If you do not do this, problems can occur if there is an element named myapp in the document. In JScript/MSHTML, identifier resolution will find a host object in the scope chain that has myapp as its property. The value of that property will be a reference to the corresponding element object, and attempting to overwrite that property value will cause a runtime error.
Add an event handler to the body's Load event. In that event handler, make your myapp.myfunc() call.
Whenever you're making your code available for consumption, you always want to make sure you're being a good citizen on the page. That means you don't want to create unnecessary global variables, and make sure ones you do create are unique enough. Thats why it's a good idea to wrap your code in an immediately-invoked function expression.
Also, it's generally just easier to do the whole thing with javascript. This is how Google analytics and Facebook plugins load their code.
<script type="text/javascript">
(function() {
var loadScript = function(src, callback) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
// modern browsers
script.onload = callback;
// IE 6 & 7
script.onreadystatechange = function() {
if (this.readyState == 'complete') {
callback();
}
}
head.appendChild(script);
};
loadScript('path/to/myscript.js', function() {
//script loaded
});
})();
</script>

document.write fallback causing jQuery to load out of order

I'm building a new site using HTML5 Boilerplate 4.0, and am running into trouble with its jQuery local fallback code. The code in question is here:
<!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script> -->
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.1.min.js"><\/script>')</script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
I'm developing locally, for now, so I've commented out the CDN line. My problem is that jQuery does load, but it loads after plugins.js and main.js, leading to undefined errors.
The closest to maybe an explanation I've found is the #4 point of this previous answer, which suggests this would be expected, but... the above is easily the most used local fallback code for jQuery, and it's H5BP, which is heavily vetted. I must be missing something, yes?
I answered a similar question some time ago.
You can do something like this:
function loadScript(pathToScript, callback) {
if (/jquery/.test(pathToScript) && window.jQuery) {
//jQuery has already been loaded so simply call the callback
callback.apply();
} else {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.type = "text/javascript";
script.src = pathToScript + "?t=" + new Date().getTime(); //prevent caching
if (callback) {
script.onload = callback;
}
head.appendChild(script);
}
}
var scripts = ['js/vendor/jquery-1.8.1.min.js', 'js/plugins.js', 'js/main.js'];
(function (i) {
if (i < scripts.length) {
var self = arguments.callee;
loadResource(scripts[i], function () {
self(++i);
});
}
})(0);
Neither did I find a precise answer on StackOverflow about this issue, however, it seems that this page covered the subject :
To sum up - creating a truly robust failover solution is not simple. We need to consider browser incompatabilities, document states and events, dependencies, deferred loading and time-outs! Thankfully tools like LABjs exist to help us ease the pain by giving us complete control over the loading of our JavaScript files.
http://happyworm.com/blog/2010/01/28/a-simple-and-robust-cdn-failover-for-jquery-14-in-one-line/
Note : solution relies on the use of LABjs
You may consider using yepnope to load your scripts in parallel with the fallback.
From their website:
yepnope.js has the capability to do resource fallbacks and still
download dependent scripts in parallel with the first.
And the code:
yepnope([{
load: 'http:/­/ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js',
complete: function () {
if (!window.jQuery) {
yepnope('local/jquery.min.js');
}
}
}, {
load: 'jquery.plugin.js',
complete: function () {
jQuery(function () {
jQuery('div').plugin();
});
}
}]);
I hope this help!

asynchronous javascript loading/executing

In this post, asynchronous .js file loading syntax, someone said, "If the async attribute is present, then the script will be executed asynchronously, as soon as it is available."
(function() {
var d=document,
h=d.getElementsByTagName('head')[0],
s=d.createElement('script');
s.type='text/javascript';
s.async=true;
s.src='/js/myfile.js';
h.appendChild(s);
}()); /* note ending parenthesis and curly brace */
My question is, what does "the script will be executed asynchronously" mean? Will this script be executed in a different thread from other javascripts in the page? If yes, should we worry about synchronization issue in the two threads?
Thanks.
Usually, when you add an external script to an HTML document, the script will need to be downloaded and executed before anything else can be done on the page. In other words, the script blocks. This can take a lot of time if there are several scripts to download.
But when you load a script asynchronously, it doesn't block. The rest of the page can be loaded and other scripts can be executed while the async script is downloading. This makes pages load faster, but this also means that you can't be sure when the async script will be executed. So you can't just start using functions and objects from the async script. You have to wait and check for the async script to load.
Example:
script1.js
var foo = "bar";
script2.js
alert(foo);
doc1.html
<script type="text/javascript" src="script1.js"></script>
<script type="text/javascript" src="script2.js"></script>
Result: "bar"
doc2.html
<script type="text/javascript" src="script1.js" async="true"></script>
<script type="text/javascript" src="script2.js"></script>
Result: "bar" or undefined, depending on whether or not script1.js has loaded yet.
No threads to worry about, though. One script executes after the other, but never both at the same time. It's just the order of execution that becomes unpredictable.
It will not be executed on different thread. You do not have to worry about thread synchronization in this case.
At some point later, after your current call stack unwinds, the download of myfile.js will complete. The browser and js framework will execute your script at some point after that.
Downloaded asynchronously, not executed asynchronously. Also, it's not necessarily executed when the download finishes.
(function(doc, script) {
var js,
fjs = doc.getElementsByTagName(script)[0],
add = function(url, id) {
if (doc.getElementById(id)) {return;}
js = doc.createElement(script);
js.src = url;
id && (js.id = id);
fjs.parentNode.insertBefore(js, fjs);
};
// Google Analytics
add(('https:' == location.protocol ? '//ssl' : '//www') + '.google-analytics.com/ga.js', 'ga');
// Google+ button
add('https://apis.google.com/js/plusone.js');
// Facebook SDK
add('//connect.facebook.net/en_US/all.js', 'facebook-jssdk');
// Twitter SDK
add('//platform.twitter.com/widgets.js', 'twitter-wjs');
}(document, 'script'));
source: https://css-tricks.com/thinking-async/

Categories

Resources