charger les scripts de manière asynchrone

j'utilise plusieurs plugins, widgets personnalisés et quelques autres bibliothèques de JQuery. résultat: j'ai plusieurs .js et .les fichiers css. Je dois créer un chargeur pour mon site parce qu'il prend un certain temps à charger. ce sera bien si je peux afficher le chargeur avant d'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 tutoriels qui me permettent d'importer une bibliothèque JavaScript de façon 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 d'essayer de trouver où est le problème, mais je ne peux pas le trouver. J'ai d'abord pensé que c'était probablement parce que certaines fonctions javascript dépendait des autres. mais je les ai chargés dans le bon ordre en utilisant la fonction time out quand un terminé j'ai procédé avec le suivant et la page se comporte toujours bizarre. par exemple, Je ne suis pas capable de cliquer sur les liens etc... des animations toujours travail même si..

anyway

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 remplacer mon index.page html avec une page qui charge tous ces fichiers de façon asynchrone. quand ajax est fait en chargeant tous ces fichiers redirigent vers la page que je prévois d'utiliser. lors de l'utilisation de la page, il ne devrait pas prendre longtemps pour charger car les fichiers devraient 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 afficher un chargeur et rediriger la page quand c'est fait...

cette idée Est-elle une bonne alternative? ou devrais-je continuer à essayer de mettre en œuvre les méthodes asynchrones?


MODIFIER

la façon dont je me charge de tout async 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 la partie étrange est que tout le travail du style plus toutes les fonctions javascript. la page est gelée pour une raison quelconque...

102
demandé sur Benjamin 2011-10-11 01:31:44

19 réponses

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, utilisez juste:

$.getScript(url, successCallback) *

de plus, il est possible que vos scripts soient chargés/exécutés avant que le document ne soit chargé, ce qui signifie que vous devez attendre document.ready avant que les événements puissent être liés aux éléments.

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

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

si vous avez une interaction particulièrement fantaisiste qui n'est pas toujours utilisée qui nécessite un script plus grand d'une sorte, il pourrait être utile pour éviter de charger ce script particulier jusqu'à ce qu'il soit nécessaire (chargement paresseux).

* les scripts chargés avec $.getScript ne seront probablement pas mis en cache


pour quiconque peut utiliser des caractéristiques modernes telles que l'objet Promise , la fonction loadScript est devenue beaucoup plus simple:

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 sachez que cette version n'accepte plus l'argument callback car la promesse retournée traitera la callback. Ce qui auparavant aurait été loadScript(src, callback) serait maintenant loadScript(src).then(callback) .

Cela a l'avantage supplémentaire d'être en mesure de détecter et de gérer les échecs, par exemple, on pourrait l'appeler...

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

...et cela permettrait de gérer les pannes de CDN avec élégance.

147
répondu zzzzBov 2017-02-20 02:31:03
Le nouvel attribut 'async' de

HTML5 est censé faire l'affaire. 'defer' est également pris en charge dans la plupart des navigateurs Si vous vous souciez D'IE.

async-the HTML

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

reporter - Le HTML

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

en analysant le nouveau code d'unité publicitaire adsense, j'ai remarqué l'attribut et une recherche m'a mené ici: http://davidwalsh.name/html5-async

25
répondu Donald Porter 2013-08-23 21:27:21

j'ai chargé les scripts de manière asynchrone (html 5 a cette fonctionnalité) quand tous les scripts où le chargement est fait j'ai redirigé la page vers index2.html où index2.html utilise les mêmes bibliothèques. Parce que les navigateurs ont un cache une fois que la page redirige vers 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.page html je charge également les images que j'ai l'intention d'utiliser afin que le navigateur place ces images sur le cache. donc, mon index.html ressemble comme:

<!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 peux placer un chargeur dans la page et quand la page est terminée chargement du chargeur va disparaître et dans une matte de millisecondes la nouvelle page sera en cours d'exécution.

7
répondu Tono Nam 2011-10-12 16:02:21

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>
6
répondu Kernel Med 2013-12-26 13:36:15

plusieurs notes:

  • s.async = true n'est pas très correct pour HTML5 doctype, correct est s.async = 'async' (en fait en utilisant true est correct , merci à amn qui l'a souligné dans le commentaire juste en dessous)
  • utiliser des temps morts pour contrôler la commande n'est pas très bon et sûr, et vous faites aussi le temps de chargement beaucoup plus grand, pour égaler la somme de tous délais d'attente!

Puisqu'il y a une raison récente de charger des fichiers de manière asynchrone, mais dans l'ordre, je recommanderais un peu plus fonctionnelle sur votre exemple (supprimer console.log pour l'utilisation de 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 = 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);
})();
6
répondu shaman.sir 2017-05-23 12:18:27

je voudrais compléter la réponse de zzzzBov avec une vérification de la présence de rappel et permettre la transmission des arguments:

    function loadScript(src, callback, args) {
      var s, r, t;
      r = false;
      s = document.createElement('script');
      s.type = 'text/javascript';
      s.src = src;
      if (typeof(callback) === 'function') {
        s.onload = s.onreadystatechange = function() {
          if (!r && (!this.readyState || this.readyState === 'complete')) {
            r = true;
            callback.apply(args);
          }
        };
      };
      t = document.getElementsByTagName('script')[0];
      t.parent.insertBefore(s, t);
    }
2
répondu Tibo 2013-07-11 19:18:39

vous pourriez trouver cet article wiki intéressant : http://ajaxpatterns.org/On-Demand_Javascript

explique comment et quand utiliser une telle technique.

1
répondu tereško 2011-10-10 21:38:55

une des raisons pour lesquelles vos scripts pourraient être chargés si lentement est si vous exécutiez tous vos scripts pendant le chargement de la page, comme ceci:

callMyFunctions();

au lieu de:

$(window).load(function() {
      callMyFunctions();
});

ce second morceau de script attend jusqu'à ce que le navigateur ait complètement chargé tout votre code Javascript avant qu'il ne commence à exécuter l'un de vos scripts, faisant apparaître à l'utilisateur que la page a chargé plus rapidement.

si vous cherchez pour améliorer l'expérience de l'utilisateur en réduisant le temps de chargement, Je n'opterais pas pour l'option "écran de chargement". À mon avis, ce serait beaucoup plus ennuyeux que d'avoir un chargement de la page plus lentement.

1
répondu therin 2011-10-10 21:51:33

je vous suggère de jeter un oeil à Modernizr . C'est une petite bibliothèque légère que vous pouvez charger de manière asynchrone votre javascript avec des fonctionnalités qui vous permettent de vérifier si le fichier est chargé et exécuter le script dans l'autre vous spécifiez.

voici un exemple de chargement jquery:

Modernizr.load([
  {
    load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js',
    complete: function () {
      if ( !window.jQuery ) {
            Modernizr.load('js/libs/jquery-1.6.1.min.js');
      }
    }
  },
  {
    // This will wait for the fallback to load and
    // execute if it needs to.
    load: 'needs-jQuery.js'
  }
]);
1
répondu Shawn Mclean 2011-10-10 22:10:36

grâce à HTML5, vous pouvez maintenant déclarer les scripts que vous voulez charger de manière asynchrone en ajoutant "async" dans la balise:

<script async>...</script>

Note: l'attribut async n'est utilisé que pour les scripts externes (et ne doit être utilisé que si l'attribut src est présent).

Note: il y a plusieurs façons d'exécuter un script externe:

  • si async est présent: le script est exécuté asynchrone avec le reste de la page (le script sera exécuté alors que la page continue de l'analyse)
  • si async n'est pas présent et que defer est présent: le script est exécuté lorsque la page a terminé l'analyse
  • si ni async ni defer ne sont présents: le script est récupéré et exécuté immédiatement, avant que le navigateur ne continue à analyser la page

voir ceci: http://www.w3schools.com/tags/att_script_async.asp

1
répondu odroz 2016-05-09 15:08:50

Voici une grande solution contemporaine au chargement asynchrone du script bien qu'elle ne s'adresse au script js qu'avec async false .

Il y a un article écrit dans www.html5rocks.com - plongée dans les eaux troubles de script de chargement .

après avoir considéré de nombreuses solutions possibles, l'auteur a conclu que l'ajout de scripts js à la fin du corps element est le meilleur moyen d'éviter de bloquer le rendu de page par les scripts js.

entre-temps, l'auteur a ajouté une autre bonne solution alternative pour les personnes qui sont désespérées de charger et d'exécuter des scripts de manière asynchrone.

considérant que vous avez quatre scripts nommés script1.js, script2.js, script3.js, script4.js alors vous pouvez le faire avec applying async = false :

[
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

Maintenant, Spec dit : Télécharger ensemble, exécuter dans l'ordre dès que tout le téléchargement.

Firefox < 3.6, Opera dit: Je n'ai aucune idée de ce qu'est cette chose" async", mais il se trouve que j'exécute des scripts ajoutés via JS dans l'ordre où ils sont ajoutés.

Safari 5.0 dit: je comprends" async", mais je ne comprends pas le paramétrage à" false " avec JS. J'exécuterai vos scripts dès qu'ils atterriront, dans n'importe quel ordre.

IE < 10 dit: Aucune idée à propos de "async", mais il existe une solution de contournement à l'aide de "onreadystatechange".

tout le reste dit: je suis votre ami, nous allons le faire selon les règles.

maintenant, le code complet avec IE < 10 contournement:

var scripts = [
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && ( pendingScripts[0].readyState == 'loaded' || pendingScripts[0].readyState == 'complete' ) ) {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we’ll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}
1
répondu asmmahmud 2017-08-03 16:45:19

bien, x.parentNode renvoie l'élément tête, vous insérez donc le script juste avant l'étiquette tête. C'est peut-être le problème.

Essayer x.parentNode.appendChild() à la place.

0
répondu alekop 2011-10-10 21:45:35

Regardez ce https://github.com/stephen-lazarionok/async-resource-loader . Il a un exemple qui montre comment charger JS, CSS et plusieurs fichiers avec une seule prise de vue.

0
répondu Stephen L. 2015-03-05 21:50:20

vous pouvez utiliser LABJS ou RequreJS

Les chargeurs de scripts

comme LABJS , RequireJS amélioreront la vitesse et la qualité de votre code.

0
répondu Kaushik 2015-04-29 05:53:45

avez-vous envisagé L'Injection Fetch? J'ai roulé une bibliothèque open source appelée fetch-inject pour traiter des cas comme ceux-ci. Voici à quoi ressemble votre chargeur en utilisant la lib:

fetcInject([
  'js/jquery-1.6.2.min.js',
  'js/marquee.js',
  'css/marquee.css',
  'css/custom-theme/jquery-ui-1.8.16.custom.css',
  'css/main.css'
]).then(() => {
  'js/jquery-ui-1.8.16.custom.min.js',
  'js/farinspace/jquery.imgpreload.min.js'
})

pour la détection de la fonction de levier de rétrocompatibilité et le retour aux éléments XHR Injection ou Script DOM, ou tout simplement dans les balises dans la page en utilisant document.write .

0
répondu Josh Habdas 2017-03-15 08:53:00

voici ma solution personnalisée pour éliminer le blocage des rendus JavaScript:

// put all your JS files here, in correct order
const libs = {
  "jquery": "https://code.jquery.com/jquery-2.1.4.min.js",
  "bxSlider": "https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.5/jquery.bxslider.min.js",
  "angular": "https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.2/angular.min.js",
  "ngAnimate": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular-animate.min.js"
}
const loadedLibs = {}
let counter = 0

const loadAsync = function(lib) {
  var http = new XMLHttpRequest()
  http.open("GET", libs[lib], true)
  http.onload = () => {
    loadedLibs[lib] = http.responseText
    if (++counter == Object.keys(libs).length) startScripts()
  }
  http.send()
}

const startScripts = function() {
  for (var lib in libs) eval(loadedLibs[lib])
  console.log("allLoaded")
}

for (var lib in libs) loadAsync(lib)

en bref, il charge tous vos scripts de manière asynchrone, puis les exécute en conséquence.

dépôt Github : https://github.com/mudroljub/js-async-loader

0
répondu Damjan Pavlica 2017-12-21 23:04:13

j'ai écrit un petit post pour aider avec cela, vous pouvez lire la suite ici https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript / , mais j'ai joint la classe helper ci-dessous. Il attendra automatiquement qu'un script se charge et retournera un attribut de fenêtre spécifié une fois qu'il se chargera.

export default class ScriptLoader {
  constructor (options) {
    const { src, global, protocol = document.location.protocol } = options
    this.src = src
    this.global = global
    this.protocol = protocol
    this.isLoaded = false
  }

  loadScript () {
    return new Promise((resolve, reject) => {
      // Create script element and set attributes
      const script = document.createElement('script')
      script.type = 'text/javascript'
      script.async = true
      script.src = `${this.protocol}//${this.src}`

      // Append the script to the DOM
      const el = document.getElementsByTagName('script')[0]
      el.parentNode.insertBefore(script, el)

      // Resolve the promise once the script is loaded
      script.addEventListener('load', () => {
        this.isLoaded = true
        resolve(script)
      })

      // Catch any errors while loading the script
      script.addEventListener('error', () => {
        reject(new Error(`${this.src} failed to load.`))
      })
    })
  }

  load () {
    return new Promise(async (resolve, reject) => {
      if (!this.isLoaded) {
        try {
          await this.loadScript()
          resolve(window[this.global])
        } catch (e) {
          reject(e)
        }
      } else {
        resolve(window[this.global])
      }
    })
  }
}

l'Utilisation est comme ceci:

const loader = new Loader({
    src: 'cdn.segment.com/analytics.js',
    global: 'Segment',
})

// scriptToLoad will now be a reference to `window.Segment`
const scriptToLoad = await loader.load()
0
répondu Zach 2018-05-04 14:49:43

Voici une petite fonction ES6 si quelqu'un veut l'utiliser dans React par exemple

import {uniqueId} from 'lodash' // optional
/**
 * @param {String} file The path of the file you want to load.
 * @param {Function} callback (optional) The function to call when the script loads.
 * @param {String} id (optional) The unique id of the file you want to load.
 */
export const loadAsyncScript = (file, callback, id) => {
  const d = document
  if (!id) { id = uniqueId('async_script') } // optional
  if (!d.getElementById(id)) {
    const tag = 'script'
    let newScript = d.createElement(tag)
    let firstScript = d.getElementsByTagName(tag)[0]
    newScript.id = id
    newScript.async = true
    newScript.src = file
    if (callback) {
      // IE support
      newScript.onreadystatechange = () => {
        if (newScript.readyState === 'loaded' || newScript.readyState === 'complete') {
          newScript.onreadystatechange = null
          callback(file)
        }
      }
      // Other (non-IE) browsers support
      newScript.onload = () => {
        callback(file)
      }
    }
    firstScript.parentNode.insertBefore(newScript, firstScript)
  } else {
    console.error(`The script with id ${id} is already loaded`)
  }
}
0
répondu JoxieMedina 2018-08-10 01:56:56

je vous suggère d'examiner les fichiers d'abord et de voir si cela vous donne une assez grande augmentation de vitesse. Si votre hôte est lent, vous pouvez essayer de mettre ce contenu statique sur un CDN.

-2
répondu Jason Miesionczek 2011-10-10 21:36:17