Before IE8 and firefox3.6, the page loads external JavaScript files (IE6, 7 will block together with images, style resources, and page rendering). In later versions, browsers all use waterfall loading, which makes page opening and rendering faster. Please note that the waterfall loading I mentioned only refers to loading rather than JS execution, javascript execution is always blocked in mainstream browsers. It is described in a simple language, that is, at the same time, the page will load only one JS file. Before the first JS file is loaded and executed, the second JS file to be introduced will not be downloaded and executed. The JS import order on the page is determined by the request order.
Let's take a look at an example of loading multiple JS files on a page in IE6:
Inline script block: embedded Javascript code block for the page, while external script is a JS file that needs to be loaded from the outside.
We set the inline script execution time to 3 seconds, external script1 loading time to 2 seconds, execution time to 3 seconds, external script2 loading time to 2 seconds, and execution time to 0 seconds (actually slightly greater than 0, the same below), external script3 loading takes 2 seconds, and execution takes 0 seconds.
We can see that it takes 15641 milliseconds for the page to load and execute JavaScript. We can get a formula:
On the same page, under IE8 and firefox3.6, we will get:
IE8: (it only takes 9 seconds, and the speed is nearly doubled)
Firefox:
From the above phenomenon, we can prove the above point of view.
Is there a solution that allows IE6/7 or chrome to display our pages faster? multiple files can be loaded at the same time without affecting the rendering of DOM elements on the page? The answer is yes.
In my previous project, I wrote similar code to process multiple external JavaScript files.
Function loadscript (URL, FN, Doc, charset ){
Doc = Doc | document;
VaR script = Doc. createelement ('script ');
Script. Language = "JavaScript ";
Script. charset = charset? Charset: 'utf-8 ';
Script. type = 'text/JavaScript ';
Script. onload = script. onreadystatechange = function (){
If (! Script. readystate | 'loaded' = script. readystate | 'complete' = script. readystate ){
FN & FN ();
Script. onload = script. onreadystatechange = NULL;
Script. parentnode. removechild (SCRIPT );
};
};
Script. src = URL;
$ ('Head') [0]. appendchild (SCRIPT );
}
When the webpage needs to dynamically call multiple JS files, we can write as follows:
Loadscript ('../jquery-1.4.2.js', function () {console. Log ('jquery-1.4.2.js loaded ')});
Loadscript ('$. wbx. js', function () {console. Log ('example/$. wbx. js loaded ')});
Loadscript ('gadgets. js', function () {console. Log ('example/gadgets. js loaded ')});
Loadscript ('jui-all. js', function () {console. Log ('example/jui-all.js loaded ')});The code in the previous section handles this function: it can dynamically load multiple JS files and execute the callback function after the file is downloaded. Of course, it is better than that. We can also get it as needed to reduce traffic and browser memory usage! It is of great benefit to websites with high concurrent requests! I used to collect statistics on the homepage of a company to reduce the traffic by 50 k. In a year, I can save tens of thousands of dollars... However, the above Code is not perfect, and new problems may occur in some applications. See the following
It is not difficult to find that the order of loading has changed! At this time, if. JS depends on B. JS, while B. JS is later than. when the JS load is complete, the "variable undefined" JS error will occur and cannot be executed.
Then our next goal is to make these external files orderly loaded into the web page. In this way, no matter whether the IQ is high or low, you will think of the queue. Good, it is the queue. It is not difficult to implement the queue in JS. Yes, just the array. We can use the array shift method, the first JS file of the array is popped up (this is the JS file we first added to the array), simulating the implementation method of the queue. However, here we have to consider one more problem: the next JS request can only start after the previous JS file is loaded. How can we determine that the previous JS file has been loaded? Code:
VaR testnode = Doc. createelement ('script'), FN, node;
Fn = testnode. readystate? Function (node, callback ){
Node. onreadystatechange = function (){
VaR rs = node. readystate;
If (rs = 'loaded' | rs = 'complete '){
// Handle memory leak in IE
Node. onreadystatechange = NULL;
Callback. Call (this );
}
};
}: Function (node, callback ){
Node. onload = callback;
};
In non-ie cases, we can easily use the onload and onerror of DOM elements to determine whether the elements have been loaded. ie does not use this set, and does not support onload judgment of script nodes, so we had to look for other solutions. Fortunately, ie's support for onreadystatechange and readystate is sufficient for us to complete this task.
The value of readystate may be:
"Uninitialized"-Original Status
"Loading"-downloading data ..
"Loaded"-Download complete
"Interactive"-execution is not completed yet.
"Complete"-script execution is complete.
In IE6/7/8, although script nodes are loaded, the results are not always loaded or complete. In addition, SRC is set first, then appended to the node tree, and SRC is set first appended to the node tree, IE7/8 processes and loads SRC files at different times. In order to reduce unnecessary troubles, we will judge both States here.
There is another problem. If a JS file needs to process the DOM node, we cannot determine whether the node has been rendered when loading Js, we need to use the classic domready to determine whether to load and execute JavaScript after rendering all DOM nodes.
Code Function domready (){
If (readybound ){
Return;
}
Readybound = true;
If (document. readystate = "complete "){
Return dequeue ();
}
If (document. addeventlistener ){
Document. addeventlistener ("domcontentloaded", dequeue, false );
Window. addeventlistener ("LOAD", dequeue, false );
}
Else
If (document. attachevent ){
Document. attachevent ("onreadystatechange", dequeue );
Window. attachevent ("onLoad", dequeue );
VaR toplevel = false;
Try {
Toplevel = Window. frameelement = NULL;
}
Catch (e ){
}
If (document.doc umentelement. doscroll & toplevel ){
Try {
// If IE is used, use the trick by Diego Perini
// Http://javascript.nwbox.com/IEContentLoaded/
Document.doc umentelement. doscroll ("Left ");
}
Catch (error ){
SetTimeout (arguments. callee, 10 );
Return;
}
Dequeue ();
}
}
}
In the early days, window. onload or defer was used. Not all browsers support defer, which can be ruled out. The window. onload event is activated only when all resources on the page are loaded. What if there are many pictures or music on the page, and the elements to be operated are below them? Therefore, W3C has implemented domcontentloaded and addeventlistener, but it is a pity that IE does not support it. Fortunately, we found readystatechange again. Knowing that the page content is loaded, we will use the doscroll provided by Diego Perini to determine whether the document node is rendered to the page. In this way, JavaScript can be executed after page rendering is complete. To some extent, we have implemented the following functions:
- Asynchronous loading speeds up page loading and saves traffic.
- Sequential loading to solve JS dependency problems
- Delayed execution. Execute JS after page rendering is complete to prevent undefined
The final implementation code is attached:/files/simon4545/nc.loader.rar