load scripts asynchronously

前端 未结 19 1025
粉色の甜心
粉色の甜心 2020-11-22 12:01

I am using several plugins, custom widgets and some other libraries from JQuery. as a result I have several .js and .css files. I need to create a loader for my site because

相关标签:
19条回答
  • 2020-11-22 12:31

    A couple solutions for async loading:

    //this function will work cross-browser for loading scripts asynchronously
    function loadScript(src, callback)
    {
      var s,
          r,
          t;
      r = false;
      s = document.createElement('script');
      s.type = 'text/javascript';
      s.src = src;
      s.onload = s.onreadystatechange = function() {
        //console.log( this.readyState ); //uncomment this line to see which ready states are called.
        if ( !r && (!this.readyState || this.readyState == 'complete') )
        {
          r = true;
          callback();
        }
      };
      t = document.getElementsByTagName('script')[0];
      t.parentNode.insertBefore(s, t);
    }
    

    If you've already got jQuery on the page, just use:

    $.getScript(url, successCallback)*

    Additionally, it's possible that your scripts are being loaded/executed before the document is done loading, meaning that you'd need to wait for document.ready before events can be bound to the elements.

    It's not possible to tell specifically what your issue is without seeing the code.

    The simplest solution is to keep all of your scripts inline at the bottom of the page, that way they don't block the loading of HTML content while they execute. It also avoids the issue of having to asynchronously load each required script.

    If you have a particularly fancy interaction that isn't always used that requires a larger script of some sort, it could be useful to avoid loading that particular script until it's needed (lazy loading).

    * scripts loaded with $.getScript will likely not be cached


    For anyone who can use modern features such as the Promise object, the loadScript function has become significantly simpler:

    function loadScript(src) {
        return new Promise(function (resolve, reject) {
            var s;
            s = document.createElement('script');
            s.src = src;
            s.onload = resolve;
            s.onerror = reject;
            document.head.appendChild(s);
        });
    }
    

    Be aware that this version no longer accepts a callback argument as the returned promise will handle callback. What previously would have been loadScript(src, callback) would now be loadScript(src).then(callback).

    This has the added bonus of being able to detect and handle failures, for example one could call...

    loadScript(cdnSource)
        .catch(loadScript.bind(null, localSource))
        .then(successCallback, failureCallback);
    

    ...and it would handle CDN outages gracefully.

    0 讨论(0)
  • 2020-11-22 12:31

    You might find this wiki article interesting : http://ajaxpatterns.org/On-Demand_Javascript

    It explains how and when to use such technique.

    0 讨论(0)
  • 2020-11-22 12:33

    I loaded the scripts asynchronously (html 5 has that feature) when all the scripts where done loading I redirected the page to index2.html where index2.html uses the same libraries. Because browsers have a cache once the page redirects to index2.html, index2.html loads in less than a second because it has all it needs to load the page. In my index.html page I also load the images that I plan on using so that the browser place those images on the cache. so my index.html looks like:

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>Project Management</title>
    
        <!-- the purpose of this page is to load all the scripts on the browsers cache so that pages can load fast from now on -->
    
        <script type="text/javascript">
    
            function stylesheet(url) {
                var s = document.createElement('link');
                s.type = 'text/css';
                s.async = true;
                s.src = url;
                var x = document.getElementsByTagName('head')[0];
                x.appendChild(s);
            }
    
            function script(url) {
                var s = document.createElement('script');
                s.type = 'text/javascript';
                s.async = true;
                s.src = url;
                var x = document.getElementsByTagName('head')[0];
                x.appendChild(s);
            }
    
            //load scritps to the catche of browser
            (function () {            
                    stylesheet('css/custom-theme/jquery-ui-1.8.16.custom.css');
                    stylesheet('css/main.css');
                    stylesheet('css/marquee.css');
                    stylesheet('css/mainTable.css');
    
                    script('js/jquery-ui-1.8.16.custom.min.js');
                    script('js/jquery-1.6.2.min.js');
                    script('js/myFunctions.js');
                    script('js/farinspace/jquery.imgpreload.min.js');
                    script('js/marquee.js');            
            })();
    
        </script>
    
        <script type="text/javascript">
           // once the page is loaded go to index2.html
            window.onload = function () {
                document.location = "index2.html";
            }
        </script>
    
    </head>
    <body>
    
    <div id="cover" style="position:fixed; left:0px; top:0px; width:100%; height:100%; background-color:Black; z-index:100;">Loading</div>
    
    <img src="images/home/background.png" />
    <img src="images/home/3.png"/>
    <img src="images/home/6.jpg"/>
    <img src="images/home/4.png"/>
    <img src="images/home/5.png"/>
    <img src="images/home/8.jpg"/>
    <img src="images/home/9.jpg"/>
    <img src="images/logo.png"/>
    <img src="images/logo.png"/>
    <img src="images/theme/contentBorder.png"/>
    
    </body>
    </html>
    

    another nice thing about this is that I may place a loader in the page and when the page is done loading the loader will go away and in a matte of milliseconds the new page will be running.

    0 讨论(0)
  • 2020-11-22 12:35

    Thanks to HTML5, you can now declare the scripts that you want to load asynchronously by adding "async" in the tag:

    <script async>...</script>
    

    Note: The async attribute is only for external scripts (and should only be used if the src attribute is present).

    Note: There are several ways an external script can be executed:

    • If async is present: The script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing)
    • If async is not present and defer is present: The script is executed when the page has finished parsing
    • If neither async or defer is present: The script is fetched and executed immediately, before the browser continues parsing the page

    See this: http://www.w3schools.com/tags/att_script_async.asp

    0 讨论(0)
  • 2020-11-22 12:35

    You can use LABJS or RequreJS

    Script loaders like LABJS, RequireJS will improve the speed and quality of your code.

    0 讨论(0)
  • 2020-11-22 12:38

    Several notes:

    • s.async = true is not very correct for HTML5 doctype, correct is s.async = 'async' (actually using true is correct, thanks to amn who pointed it out in the comment just below)
    • Using timeouts to control the order is not very good and safe, and you also make the loading time much larger, to equal the sum of all timeouts!

    Since there is a recent reason to load files asynchronously, but in order, I'd recommend a bit more functional-driven way over your example (remove console.log for production use :) ):

    (function() {
        var prot = ("https:"===document.location.protocol?"https://":"http://");
    
        var scripts = [
            "path/to/first.js",
            "path/to/second.js",
            "path/to/third.js"
        ];
    
        function completed() { console.log('completed'); }  // FIXME: remove logs
    
        function checkStateAndCall(path, callback) {
            var _success = false;
            return function() {
                if (!_success && (!this.readyState || (this.readyState == 'complete'))) {
                    _success = true;
                    console.log(path, 'is ready'); // FIXME: remove logs
                    callback();
                }
            };
        }
    
        function asyncLoadScripts(files) {
            function loadNext() { // chain element
                if (!files.length) completed();
                var path = files.shift();
                var scriptElm = document.createElement('script');
                scriptElm.type = 'text/javascript';
                scriptElm.async = true;
                scriptElm.src = prot+path;
                scriptElm.onload = scriptElm.onreadystatechange = \
                    checkStateAndCall(path, loadNext); // load next file in chain when
                                                       // this one will be ready 
                var headElm = document.head || document.getElementsByTagName('head')[0];
                headElm.appendChild(scriptElm);
            }
            loadNext(); // start a chain
        }
    
        asyncLoadScripts(scripts);
    })();
    
    0 讨论(0)
提交回复
热议问题