The previous two articles have introduced how to achieve this step by dynamically loading JS files or JS modules.
First, the module loading and callback functions are separated by a synchronization policy, and then the module loading and callback functions are separated by an asynchronous policy.
This article mainly aims to explain how to optimize the asynchronous policy and implement random loading (non-sequential loading Module). After the page is Ready, the file is loaded. First, let's take a look at the issues left over from the previous article.
1. Load the page after Ready
2. Add modules as needed for loading
Looking at the first question, this question is actually quite simple, mainly listening to The DOMContentLoaded event on the page. I will not explain it here. I will search for a bunch of answers on the Internet and directly go to the code.
Copy codeThe Code is as follows:
Using. ready = function (callback ){
ReadyList. push (callback );
If (document. addEventListener ){
Document. addEventListener ("DOMContentLoaded", _ ready, false );
Return;
}
// For IE
Var domReady = function (){
Try {
Document.doc umentElement. doScroll ("left ");
_ Ready ();
} Catch (ex ){
SetTimeout (domReady, 1 );
Return;
}
}
DomReady ();
}
The most incomprehensible part of this Code is
Copy codeThe Code is as follows:
Document.doc umentElement. doScroll ("left ");
Here is actually the page loading event of IE. Simply put, after the labels in IE are loaded, Scroll can be operated. Then, based on this principle, determine whether the page loading in IE is complete.
There is a _ ready function, which is used to execute all the loaded functions after page loading. Paste the code
(Edit this section: After the page is loaded, the Ready function is not the window of native JS in our thinking. load: Simply put, the DOM structure in the page is loaded. For more information, see Baidu and google)
Copy codeThe Code is as follows:
Var readyList = [];
Var _ ready = function (){
While (readyList. length> 0 ){
Var func = readyList. shift ();
Func ();
}
Document. removeEventListener ("DOMContentLoaded", _ ready, false );
}
The following is the focus of this blog. Let's take a look at the code first.
Copy codeThe Code is as follows:
Using. asyn = function (callback ){
AsynQueue. push (callback );
If (! _ ExecAsyn. isRunning ){
_ ExecAsyn ();
}
}
It still notifies Using to load the required module, but adds an asynQueue array and the _ execAsyn function to it. Their functions are as follows:
AsynQueue is a function used to save callback after asynchronous loading. It is an array and can be understood as a queue for creating a function.
_ ExecAsyn is used to execute the stored callback functions, that is, to execute the stored functions one by one. Let's take a look at the code and comment out the functions of each line in the code.
Copy codeThe Code is as follows:
Var _ execAsyn = function (){
// Create a variable to cache the function to be executed
Var func = null;
// If there are still unexecuted functions in the queue, perform the operation
If (asynQueue. length> 0 ){
// Change the _ execAsyn function to the running state.
_ ExecAsyn. isRunning = true;
// Obtain the first function to be executed in the queue
Func = asynQueue. shift ();
// Call the asynchronous loading module's Using. fn. script Function and input the callback function to be executed after loading.
Using. fn. script (function (){
// The function to be executed
Func ();
// Iteration _ execAsyn until there is no function to be executed in the queue
_ ExecAsyn ();
});
// If no function needs to be executed in the queue
} Else {
// Change the running status of _ execAsyn to false.
_ ExecAsyn. isRunning = false;
}
}
There is nothing special about this function. To put it bluntly, it is to execute the functions to be executed one by one. The only thing that needs to be noted is why iteration is used instead of loop when queue operations are performed. That's why
1. New functions may need to be executed in the queue at any time. If a loop is used, the latest functions may not be executed because the functions are always inserted to the end of the queue.
2. Using. fn. script is asynchronous. If it is a loop, the current function has not been fully executed, and the next function may have entered the execution status. So, in itself, the speed of executing several functions at the same time may be higher. Why should we limit the parallelism of multiple functions here? The reason is also very simple, because each time the function in the execution queue needs to load the corresponding module, if the two or more functions that depend on the same module need to be executed in parallel, the same module may be loaded multiple times, and subsequent function execution may fail, resulting in exceptions.
This is the core of UsingJS. I have added the Using. Class. create function, which is mentioned at the end of the javascript dynamic loading article.
Finally, let's take a look at the page usage:
Copy codeThe Code is as follows:
<Script type = "text/javascript" src = "js/using-0.4.2.min.js"> </script>
<Script type = "text/javascript">
Using ("jq ");
Using ("UserView ");
Using ("jq ");
Using. ready (function (){
Using. asyn (function (){
$ ("# Panel"). click (function (){
Alert ("by jquery ");
});
});
});
Using. ready (function (){
Using ("Http ");
Using. asyn (function (){
Var http = new Using. Modules. Http ();
Http. set ("xxx ");
Http. show ();
});
Using. asyn (function (){
Var h = new Using. Modules. Http ();
H. set ("ooo ");
H. show ();
});
Using ("jq ");
Using. asyn (function (){
$ ("# Panel"). click (function (){
Alert ("loaded jquery ");
});
});
});
</Script>
This piece of code is deliberately loaded repeatedly. After multiple Ready events and Ready events, the Using guide package is executed.
There is something worth special attention.
Copy codeThe Code is as follows:
Using ("Http ");
Using. asyn (function (){
Var http = new Using. Modules. Http ();
Http. set ("xxx ");
Http. show ();
});
// If you use
// Var ht = new Using. Modules. Http ();
// It indicates that Using. Modules. Http is not a constructor.
// The reason is
// All operations are asynchronous. When this sentence is executed, the loading of the Using ("Http") module may not be completed.
// This is the mistake that Zhongmou will make when using the package for multiple friends. It always thinks everything is fine after the package is imported.
// Yes, it should be like this. The package can be referenced anywhere after being imported.
// But there must be a premise that the module has to be loaded.
// Write all the code in Using. asyn.
Using. asyn (function (){
Var h = new Using. Modules. Http ();
H. set ("ooo ");
H. show ();
});
Download UsingJS