137 votes

scripts de chargement asynchrone

Je suis à l'aide de plusieurs plugins, widgets personnalisés et quelques autres bibliothèques de JQuery. résultat: j'ai plusieurs .js et .les fichiers css. J'ai besoin de créer un chargeur pour mon site, parce que ça prend un certain temps à charger. il sera bon si je peux afficher le chargeur avant de l'importer tous les:

<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
... 
....
 etc

J'ai trouvé plusieurs tutos qui me permettent d'importer une bibliothèque JavaScript asynchrone. par exemple je peux faire quelque chose comme:

  (function () {
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.async = true;
        s.src = 'js/jquery-ui-1.8.16.custom.min.js';
        var x = document.getElementsByTagName('script')[0];
        x.parentNode.insertBefore(s, x);
    })();

pour une raison quelconque, quand je fais la même chose pour tous mes fichiers les pages ne fonctionne pas. J'ai essayé pendant si longtemps pour essayer de trouver où est le problème, mais j'ai juste ne peut pas le trouver. J'ai d'abord pensé que c'était probablement parce que certaines fonctions javascript dépendait des autres. mais je l'ai chargé dans le bon ordre, en utilisant le temps hors fonction lorsque l'on terminées, j'ai procédé à la prochaine et la page se comporte encore bizarre. par exemple, je ne suis pas en mesure de cliquer sur les liens etc... les animations fonctionnent toujours bien..

De toute façon

Voici ce que j'ai pensé... je crois que les navigateurs ont un cache c'est pourquoi il faut beaucoup de temps pour charger la page pour la première fois et la prochaine fois c'est rapide. donc, ce que je pense faire c'est de remplacer mon index.html page avec une page qui se charge de tous ces fichiers de manière asynchrone. lors de l'ajax est fait, le chargement de tous les fichiers rediriger vers la page que j'ai l'intention de l'utiliser. lors de l'utilisation de la page, il ne devrait pas être long à charger depuis les fichiers doivent déjà être inclus dans le cache du navigateur. sur ma page d'index (page où .js et .fichier css chargés de manière asynchrone) je ne me soucie pas d'avoir des erreurs. Je vais juste être l'affichage d'un chargeur et la redirection de la page lorsque vous avez terminé...

Cette idée est-elle une bonne alternative? ou devrais-je continuer à essayer sur la mise en œuvre de la manière asynchrone méthodes?


MODIFIER

la façon dont je le charge tout asynchrone, c'est comme:

importScripts();

function importScripts()
{
    //import: jquery-ui-1.8.16.custom.min.js
    getContent("js/jquery-1.6.2.min.js",function (code) {
                var s = document.createElement('script');
                s.type = 'text/javascript';
                //s.async = true;
                s.innerHTML=code;
                var x = document.getElementsByTagName('script')[0];
                x.parentNode.insertBefore(s, x);
                setTimeout(insertNext1,1);
            });


    //import: jquery-ui-1.8.16.custom.min.js
    function insertNext1()
    {
        getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext2,1);
                });
    }

    //import: jquery-ui-1.8.16.custom.css
    function insertNext2()
    {

        getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext3,1);
                });
    }

    //import: main.css
    function insertNext3()
    {

        getContent("css/main.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext4,1);
                });
    }

    //import: jquery.imgpreload.min.js
    function insertNext4()
    {
        getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext5,1);
                });
    }


    //import: marquee.js
    function insertNext5()
    {
        getContent("js/marquee.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext6,1);
                });
    }


    //import: marquee.css
    function insertNext6()
    {

        getContent("css/marquee.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext,1);
                });
    }



    function insertNext()
    {
        setTimeout(pageReadyMan,10);        
    }
}


// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
     // attempt to create the XMLHttpRequest and make the request
     try
     {
        var asyncRequest; // variable to hold XMLHttpRequest object
        asyncRequest = new XMLHttpRequest(); // create request object

        // register event handler
        asyncRequest.onreadystatechange = function(){
            stateChange(asyncRequest, callBackFunction);
        } 
        asyncRequest.open( 'GET', url, true ); // prepare the request
        asyncRequest.send( null ); // send the request
     } // end try
     catch ( exception )
     {
        alert( 'Request failed.' );
     } // end catch
} // end function getContent

// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
     if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
     {
           callBackFunction(asyncRequest.responseText);
     } // end if
} // end function stateChange

et ce qui est curieux, c'est que tout le style de travail en plus de toutes les fonctions javascript. la page est gelé pour quelque raison que...

200voto

zzzzBov Points 62084

Un couple de solutions pour le chargement asynchrone:

//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);
}

Si vous avez déjà jQuery sur la page, il suffit d'utiliser

$.getScript(url, successCallback)

En outre, il est possible que vos scripts sont en cours de chargement/exécuté avant que le document est terminé le chargement, ce qui signifie que vous auriez besoin d'attendre pour document.ready avant les événements peuvent être liés aux éléments.

Il n'est pas possible de dire précisément ce que votre problème est, sans voir le code.

La solution la plus simple est de garder tous vos scripts inline au bas de la page, de cette façon, ils n'ont pas de bloquer le chargement du contenu HTML, alors qu'ils exécutent. Il évite aussi le problème d'avoir à charger de manière asynchrone chaque scénario.

Si vous avez une très chics interaction qui n'est pas toujours utilisé qui nécessite une plus grande script de la sorte, il pourrait être utile pour éviter de chargement du script jusqu'à ce qu'il est nécessaire (lazy loading).

38voto

Donald Porter Points 45

HTML5, le nouveau "asynchrone" attribut est censé faire l'affaire. "différer" est également pris en charge dans la plupart des navigateurs, si vous vous souciez de IE.

async: Le code HTML

<script async src="siteScript.js" onload="myInit()"></script>

reporter: Le code HTML

<script defer src="siteScript.js" onload="myInit()"></script>

Lors de l'analyse de la nouvelle annonce adsense code d'unité, j'ai remarqué l'attribut et une recherche de plomb-moi ici: http://davidwalsh.name/html5-async

9voto

Tono Nam Points 4465

J'ai chargé les scripts de manière asynchrone (html 5 a) lorsque tous les scripts où terminé le chargement j'ai redirigé la page d'index2.html où index2.html utilise les mêmes bibliothèques. Parce que les navigateurs ont un cache, une fois la redirection de la page d'index2.html, index2.html charges en moins d'une seconde, car il a tout ce qu'il faut pour charger la page. Dans mon index.html page, j'ai également charger les images que je vous prévoyez sur l'utilisation de sorte que le navigateur de placer ces images dans le cache. donc, mon index.html ressemble:

<!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>

une autre bonne chose à ce sujet est que je peut mettre un chargeur dans la page et quand la page est terminé le chargement, le chargeur va aller loin et dans un masque de millisecondes la nouvelle page sera en cours d'exécution.

8voto

shaman.sir Points 1056

Plusieurs remarques:

  • s.async = true n'est pas très correct pour un doctype HTML5, corriger s.async = 'async'
  • À l'aide de délais d'attente pour le contrôle de l'ordre n'est pas très bonne et sûre, et vous pouvez aussi prendre le temps de chargement beaucoup plus grande, égale à la somme de tous les délais d'attente!

Puisqu'il y a un récent raison pour charger les fichiers de façon asynchrone, mais dans l'ordre, je vous recommande un peu plus fonctionnelles de méthode sur votre exemple (supprimer console.log pour une utilisation en production :) ):

(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 = 'async';
            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);
})();

8voto

Kernel Med Points 31

Exemple de google

<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js?onload=onLoadCallback';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X