Domanda

Come puoi caricare in modo affidabile e dinamico un file JavaScript?Questo potrà essere utilizzato per implementare un modulo o un componente che, una volta "inizializzato", caricherà dinamicamente tutti gli script della libreria JavaScript necessari su richiesta.

Al client che utilizza il componente non è richiesto di caricare tutti i file di script della libreria (e di inserire manualmente <script> tag nella loro pagina web) che implementano questo componente - solo il file di script del componente "principale".

In che modo le librerie JavaScript tradizionali ottengono questo risultato (Prototype, jQuery, ecc.)? Questi strumenti uniscono più file JavaScript in un'unica versione "build" ridistribuibile di un file di script?Oppure eseguono un caricamento dinamico degli script di "libreria" ausiliari?

Un'aggiunta a questa domanda: esiste un modo per gestire l'evento dopo il caricamento di un file JavaScript incluso dinamicamente? Il prototipo ha document.observe per eventi a livello di documento.Esempio:

document.observe("dom:loaded", function() {
  // initially hide all containers for tab content
  $$('div.tabcontent').invoke('hide');
});

Quali sono gli eventi disponibili per un elemento di script?

È stato utile?

Soluzione

Puoi scrivere tag di script dinamici (usando Prototipo):

new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});

Il problema qui è che non lo sappiamo Quando il file di script esterno è completamente caricato.

Spesso vogliamo il nostro codice dipendente nella riga successiva e ci piace scrivere qualcosa come:

if (iNeedSomeMore) {
    Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
    myFancyMethod(); // cool, no need for callbacks!
}

Esiste un modo intelligente per inserire dipendenze di script senza la necessità di callback.Devi semplicemente estrarre lo script tramite a richiesta AJAX sincrona e valutare la sceneggiatura a livello globale.

Se usi Prototype il metodo Script.load assomiglia a questo:

var Script = {
    _loadedScripts: [],
    include: function(script) {
        // include script only once
        if (this._loadedScripts.include(script)) {
            return false;
        }
        // request file synchronous
        var code = new Ajax.Request(script, {
            asynchronous: false,
            method: "GET",
            evalJS: false,
            evalJSON: false
        }).transport.responseText;
        // eval code on global level
        if (Prototype.Browser.IE) {
            window.execScript(code);
        } else if (Prototype.Browser.WebKit) {
            $$("head").first().insert(Object.extend(
                new Element("script", {
                    type: "text/javascript"
                }), {
                    text: code
                }
            ));
        } else {
            window.eval(code);
        }
        // remember included script
        this._loadedScripts.push(script);
    }
};

Altri suggerimenti

Non è necessario importare/includere/richiedere in Javascript, ma ci sono due modi principali per ottenere ciò che desideri:

1 - Puoi caricarlo con una chiamata AJAX quindi utilizzare eval.

Questo è il modo più semplice ma è limitato al tuo dominio a causa delle impostazioni di sicurezza di Javascript e l'utilizzo di eval apre la porta a bug e hack.

2 - Aggiungi un tag script con l'URL dello script nell'HTML.

Sicuramente il modo migliore per procedere.Puoi caricare lo script anche da un server esterno ed è pulito poiché utilizzi il parser del browser per valutare il codice.Puoi inserire il tag nella testa della pagina web o nella parte inferiore del corpo.

Entrambe queste soluzioni sono discusse e illustrate qui.

Ora, c’è un grosso problema che devi conoscere.Ciò implica che carichi il codice da remoto.I browser Web moderni caricheranno il file e continueranno a eseguire lo script corrente perché caricano tutto in modo asincrono per migliorare le prestazioni.

Significa che se usi questi trucchi direttamente, non sarai in grado di usare il codice appena caricato nella riga successiva dopo averne chiesto il caricamento, perché sarà ancora in fase di caricamento.

PER ESEMPIO :my_lovely_script.js contiene MySuperObject

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

Quindi ricarichi la pagina premendo F5.E funziona!Confusione...

Quindi cosa fare al riguardo?

Bene, puoi usare il trucco suggerito dall'autore nel link che ti ho dato.In sintesi, per chi ha fretta, usa en event per eseguire una funzione di callback quando lo script viene caricato.Quindi puoi inserire tutto il codice utilizzando la libreria remota nella funzione di callback.PER ESEMPIO :

function loadScript(url, callback)
{
    // adding the script tag to the head as suggested before
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = url;

   // then bind the event to the callback function 
   // there are several events for cross browser compatibility
   script.onreadystatechange = callback;
   script.onload = callback;

   // fire the loading
   head.appendChild(script);
}

Quindi scrivi il codice che desideri utilizzare DOPO che lo script è stato caricato in una funzione lambda:

var myPrettyCode = function() {
    // here, do what ever you want
};

Quindi esegui tutto questo:

loadScript("my_lovely_script.js", myPrettyCode);

Ok ho capito.Ma è una seccatura scrivere tutte queste cose.

Bene, in tal caso, puoi utilizzare come sempre il fantastico framework gratuito jQuery, che ti consente di fare esattamente la stessa cosa in una riga:

$.getScript("my_lovely_script.js", function() {
    alert("Script loaded and executed.");
    // here you can use anything you defined in the loaded script
});

Ho usato un versione molto meno complicata di recente con jQuery:

<script src="scripts/jquery.js"></script>
<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  var $head = $("head");
  for (var i = 0; i < js.length; i++) {
    $head.append("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

Ha funzionato benissimo in tutti i browser in cui l'ho provato:IE6/7, Firefox, Safari, Opera.

Aggiornamento: Versione senza jQuery:

<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  for (var i = 0, l = js.length; i < l; i++) {
    document.getElementsByTagName("head")[0].innerHTML += ("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

Ho fatto sostanzialmente la stessa cosa che hai fatto tu Adam, ma con una leggera modifica per assicurarmi di aggiungere il tag head per portare a termine il lavoro.Ho semplicemente creato una funzione di inclusione (codice seguente) per gestire sia i file script che i file CSS.

Questa funzione controlla anche che lo script o il file CSS non sia già stato caricato dinamicamente.Non controlla i valori codificati manualmente e potrebbe esserci stato un modo migliore per farlo, ma è servito allo scopo.

function include( url, type ){
    // First make sure it hasn't been loaded by something else.
    if( Array.contains( includedFile, url ) )
        return;

    // Determine the MIME-type
    var jsExpr = new RegExp( "js$", "i" );
    var cssExpr = new RegExp( "css$", "i" );
    if( type == null )
        if( jsExpr.test( url ) )
            type = 'text/javascript';
        else if( cssExpr.test( url ) )
            type = 'text/css';

    // Create the appropriate element.
    var tag = null;
    switch( type ){
        case 'text/javascript' :
            tag = document.createElement( 'script' );
            tag.type = type;
            tag.src = url;
            break;
        case 'text/css' :
            tag = document.createElement( 'link' );
            tag.rel = 'stylesheet';
            tag.type = type;
            tag.href = url;
            break;
    }

    // Insert it to the <head> and the array to ensure it is not
    // loaded again.
    document.getElementsByTagName("head")[0].appendChild( tag );
    Array.add( includedFile, url );
}

un'altra risposta fantastica

$.getScript("my_lovely_script.js", function(){


   alert("Script loaded and executed.");
  // here you can use anything you defined in the loaded script

 });

https://stackoverflow.com/a/950146/671046

Ecco qualche esempio di codice che ho trovato...qualcuno ha un modo migliore?

  function include(url)
  {
    var s = document.createElement("script");
    s.setAttribute("type", "text/javascript");
    s.setAttribute("src", url);
    var nodes = document.getElementsByTagName("*");
    var node = nodes[nodes.length -1].parentNode;
    node.appendChild(s);
  }

Se hai già caricato jQuery, dovresti usare $.getScript.

Questo ha un vantaggio rispetto alle altre risposte qui in quanto hai una funzione di callback incorporata (per garantire che lo script venga caricato prima dell'esecuzione del codice dipendente) e puoi controllare la memorizzazione nella cache.

qualcuno ha un modo migliore?

Penso che aggiungere semplicemente lo script al corpo sarebbe più semplice rispetto ad aggiungerlo all'ultimo nodo della pagina.Cosa ne pensi di questo:

function include(url) {
  var s = document.createElement("script");
  s.setAttribute("type", "text/javascript");
  s.setAttribute("src", url);
  document.body.appendChild(s);
}

ho usato ancora un'altra soluzione che ho trovato in rete...questo è sotto Creative Commons e questo controlla se la fonte è stata inclusa prima di chiamare la funzione ...

puoi trovare il file qui: include.js

/** include - including .js files from JS - bfults@gmail.com - 2005-02-09
 ** Code licensed under Creative Commons Attribution-ShareAlike License 
 ** http://creativecommons.org/licenses/by-sa/2.0/
 **/              
var hIncludes = null;
function include(sURI)
{   
  if (document.getElementsByTagName)
  {   
    if (!hIncludes)
    {
      hIncludes = {}; 
      var cScripts = document.getElementsByTagName("script");
      for (var i=0,len=cScripts.length; i < len; i++)
        if (cScripts[i].src) hIncludes[cScripts[i].src] = true;
    }
    if (!hIncludes[sURI])
    {
      var oNew = document.createElement("script");
      oNew.type = "text/javascript";
      oNew.src = sURI;
      hIncludes[sURI]=true;
      document.getElementsByTagName("head")[0].appendChild(oNew);
    }
  }   
} 

Ho appena scoperto una fantastica funzionalità in YUI3 (al momento in cui scrivo disponibile nella versione di anteprima).Puoi facilmente inserire dipendenze alle librerie YUI e ai moduli "esterni" (quello che stai cercando) senza troppo codice: Caricatore YUI.

Risponde anche alla tua seconda domanda riguardante la funzione che viene chiamata non appena viene caricato il modulo esterno.

Esempio:

YUI({
    modules: {
        'simple': {
            fullpath: "http://example.com/public/js/simple.js"
        },
        'complicated': {
            fullpath: "http://example.com/public/js/complicated.js"
            requires: ['simple']  // <-- dependency to 'simple' module
        }
    },
    timeout: 10000
}).use('complicated', function(Y, result) {
    // called as soon as 'complicated' is loaded
    if (!result.success) {
        // loading failed, or timeout
        handleError(result.msg);
    } else {
        // call a function that needs 'complicated'
        doSomethingComplicated(...);
    }
});

Ha funzionato perfettamente per me e ha il vantaggio di gestire le dipendenze.Fare riferimento alla documentazione YUI per un file esempio con il calendario YUI 2.

Se vuoi un SINCRONIZZAZIONE caricamento dello script, è necessario aggiungere il testo dello script direttamente al tag HTML HEAD.Aggiungendolo come si attiverà un file ASINC carico.Per caricare il testo dello script da un file esterno in modo sincrono, utilizzare XHR.Di seguito un rapido esempio (utilizza parti di altre risposte in questo e altri post):

/*sample requires an additional method for array prototype:*/

if (Array.prototype.contains === undefined) {
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) { if (this[i] === obj) return true; }
    return false;
};
};

/*define object that will wrap our logic*/
var ScriptLoader = {
LoadedFiles: [],

LoadFile: function (url) {
    var self = this;
    if (this.LoadedFiles.contains(url)) return;

    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                self.LoadedFiles.push(url);
                self.AddScript(xhr.responseText);
            } else {
                if (console) console.error(xhr.statusText);
            }
        }
    };
    xhr.open("GET", url, false);/*last parameter defines if call is async or not*/
    xhr.send(null);
},

AddScript: function (code) {
    var oNew = document.createElement("script");
    oNew.type = "text/javascript";
    oNew.textContent = code;
    document.getElementsByTagName("head")[0].appendChild(oNew);
}
};

/*Load script file. ScriptLoader will check if you try to load a file that has already been loaded (this check might be better, but I'm lazy).*/

ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
/*this will be executed right after upper lines. It requires jquery to execute. It requires a HTML input with id "tb1"*/
$(function () { alert($('#tb1').val()); });

La tecnica che utilizziamo al lavoro è richiedere il file javascript utilizzando una richiesta AJAX e quindi eval() il risultato.Se stai utilizzando la libreria prototipo, supportano questa funzionalità nella chiamata Ajax.Request.

jquery mi ha risolto questo problema con la sua funzione .append()- utilizzato per caricare il pacchetto completo dell'interfaccia utente jquery

/*
 * FILENAME : project.library.js
 * USAGE    : loads any javascript library
 */
    var dirPath = "../js/";
    var library = ["functions.js","swfobject.js","jquery.jeditable.mini.js","jquery-ui-1.8.8.custom.min.js","ui/jquery.ui.core.min.js","ui/jquery.ui.widget.min.js","ui/jquery.ui.position.min.js","ui/jquery.ui.button.min.js","ui/jquery.ui.mouse.min.js","ui/jquery.ui.dialog.min.js","ui/jquery.effects.core.min.js","ui/jquery.effects.blind.min.js","ui/jquery.effects.fade.min.js","ui/jquery.effects.slide.min.js","ui/jquery.effects.transfer.min.js"];

    for(var script in library){
        $('head').append('<script type="text/javascript" src="' + dirPath + library[script] + '"></script>');
    }

Usare - nella testa del tuo html/php/etc dopo aver importato jquery.js dovresti semplicemente includere questo file in questo modo per caricare l'intera libreria aggiungendolo alla testa...

<script type="text/javascript" src="project.library.js"></script>

Mantienilo bello, breve, semplice e gestibile!:]

// 3rd party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
    FULL_PATH + 'plugins/script.js'      // Script example
    FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library 
    FULL_PATH + 'plugins/crypto-js/hmac-sha1.js',      // CryptoJS
    FULL_PATH + 'plugins/crypto-js/enc-base64-min.js'  // CryptoJS
];

function load(url)
{
    var ajax = new XMLHttpRequest();
    ajax.open('GET', url, false);
    ajax.onreadystatechange = function ()
    {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4)
        {
            switch(ajax.status)
            {
                case 200:
                    eval.apply( window, [script] );
                    console.log("library loaded: ", url);
                    break;
                default:
                    console.log("ERROR: library not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

 // initialize a single load 
load('plugins/script.js');

// initialize a full load of scripts
if (s.length > 0)
{
    for (i = 0; i < s.length; i++)
    {
        load(s[i]);
    }
}

Questo codice è semplicemente un breve esempio funzionale Potevo richiedono funzionalità aggiuntive per il supporto completo su qualsiasi (o data) piattaforma.

C'è un nuovo standard ECMA proposto chiamato importazione dinamica, recentemente incorporato in Chrome e Safari.

const moduleSpecifier = './dir/someModule.js';

import(moduleSpecifier)
   .then(someModule => someModule.foo()); // executes foo method in someModule

Esistono script progettati appositamente per questo scopo.

sìnope.js è integrato in Modernizr e lab.js è una versione più ottimizzata (ma meno facile da usare.

Non consiglierei di farlo attraverso una grande libreria come jquery o prototipo, perché uno dei principali vantaggi di un caricatore di script è la possibilità di caricare gli script in anticipo - non dovresti aspettare fino al caricamento di jquery e di tutti gli elementi dom prima eseguendo un controllo per vedere se si desidera caricare dinamicamente uno script.

Ho scritto un semplice modulo che automatizza il lavoro di importazione/inclusione degli script dei moduli in JavaScript.Fai un tentativo e per favore lascia qualche feedback!:) Per una spiegazione dettagliata del codice fare riferimento a questo post del blog: http://stamat.wordpress.com/2013/04/12/javascript-require-import-include-modules/

var _rmod = _rmod || {}; //require module namespace
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark the root directory of your library, any library


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };

    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

//you can rename based on your liking. I chose require, but it can be called include or anything else that is easy for you to remember or write, except import because it is reserved for future use.
var require = function(script_name) {
    var np = script_name.split('.');
    if (np[np.length-1] === '*') {
        np.pop();
        np.push('_all');
    }

    script_name = np.join('.');
    var uri = _rmod.libpath + np.join('/')+'.js';
    if (!_rmod.loading.scripts.hasOwnProperty(script_name) 
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri, 
            _rmod.requireCallback, 
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};

// ----- USAGE -----

require('ivar.util.array');
require('ivar.util.string');
require('ivar.net.*');

ready(function(){
    //do something when required scripts are loaded
});

Mi sono perso in tutti questi esempi ma oggi avevo bisogno di caricare un .js esterno dal mio .js principale e ho fatto questo:

document.write("<script src='https://www.google.com/recaptcha/api.js'></script>");

Qui è semplice con callback e supporto IE:

function loadScript(url, callback) {

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState) { //IE
        script.onreadystatechange = function () {
            if (script.readyState == "loaded" || script.readyState == "complete") {
                script.onreadystatechange = null;
                callback();
            }
        };
    } else { //Others
        script.onload = function () {
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

loadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {

     //jQuery loaded
     console.log('jquery loaded');

});

Ecco un semplice esempio di funzione per caricare file JS.Punti rilevanti:

  • non hai bisogno di jQuery, quindi puoi usarlo inizialmente per caricare anche il file jQuery.js
  • è asincrono con la richiamata
  • garantisce che venga caricato una sola volta, poiché mantiene un allegato con il record degli URL caricati, evitando così l'utilizzo della rete
  • contrariamente a jQuery $.ajax O $.getScript puoi usare nonces, risolvendo così i problemi con CSP unsafe-inline.Basta usare la proprietà script.nonce
var getScriptOnce = function() {

    var scriptArray = []; //array of urls (closure)

    //function to defer loading of script
    return function (url, callback){
        //the array doesn't have such url
        if (scriptArray.indexOf(url) === -1){

            var script=document.createElement('script');
            script.src=url;
            var head=document.getElementsByTagName('head')[0],
                done=false;

            script.onload=script.onreadystatechange = function(){
                if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
                    done=true;
                    if (typeof callback === 'function') {
                        callback();
                    }
                    script.onload = script.onreadystatechange = null;
                    head.removeChild(script);

                    scriptArray.push(url);
                }
            };

            head.appendChild(script);
        }
    };
}();

Ora lo usi semplicemente

getScriptOnce("url_of_your_JS_file.js");

Una battuta assurda, per chi pensa che caricare una libreria js non debba richiedere più di una riga di codice :P

await new Promise((resolve, reject) => {let js = document.createElement("script"); js.src="mylibrary.js"; js.onload=resolve; js.onerror=reject; document.body.appendChild(js)});

Ovviamente se lo script che volete importare è un modulo potete utilizzare il file import(...) funzione.

tutte le principali librerie Javascript come jscript, prototipo, YUI supportano il caricamento di file di script.Ad esempio, in YUI, dopo aver caricato il core puoi eseguire le seguenti operazioni per caricare il controllo del calendario

var loader = new YAHOO.util.YUILoader({

    require: ['calendar'], // what components?

    base: '../../build/',//where do they live?

    //filter: "DEBUG",  //use debug versions (or apply some
                        //some other filter?

    //loadOptional: true, //load all optional dependencies?

    //onSuccess is the function that YUI Loader
    //should call when all components are successfully loaded.
    onSuccess: function() {
        //Once the YUI Calendar Control and dependencies are on
        //the page, we'll verify that our target container is 
        //available in the DOM and then instantiate a default
        //calendar into it:
        YAHOO.util.Event.onAvailable("calendar_container", function() {
            var myCal = new YAHOO.widget.Calendar("mycal_id", "calendar_container");
            myCal.render();
        })
     },

    // should a failure occur, the onFailure function will be executed
    onFailure: function(o) {
        alert("error: " + YAHOO.lang.dump(o));
    }

 });

// Calculate the dependency and insert the required scripts and css resources
// into the document
loader.insert();

So che la mia risposta è un po' tardi per questa domanda, ma ecco un ottimo articolo in www.html5rocks.com - Immergiti profondamente nelle acque torbide del caricamento degli script .

In quell'articolo si conclude che, per quanto riguarda il supporto del browser, il modo migliore per caricare dinamicamente il file JavaScript senza bloccare il rendering del contenuto è il seguente:

Considerando che hai quattro script denominati script1.js, script2.js, script3.js, script4.js allora puoi farlo con applicazione asincrona = 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);
});

Ora, Spec dice:Scaricali insieme, eseguili in ordine non appena vengono scaricati tutti.

Firefox < 3.6, Opera dice: Non ho idea di cosa sia questa cosa "asincrona", ma si dà il caso che esegua gli script aggiunti tramite JS nell'ordine in cui vengono aggiunti.

Safari 5.0 dice: Capisco "asincrono", ma non capisco come impostarlo su "falso" con JS.Eseguirò i tuoi script non appena arriveranno, in qualunque ordine.

IE < 10 dice: Nessuna idea di "asincrono", ma esiste una soluzione alternativa utilizzando "onreadystatechange".

Tutto il resto dice: Sono tuo amico, lo faremo secondo le regole.

Ora, il codice completo con la soluzione alternativa IE <10:

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') {
    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>');
  }
}

Alcuni trucchi e minimizzazioni dopo, sono 362 byte

!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
  "//other-domain.com/1.js",
  "2.js"
])

Qualcosa come questo...

<script>
     $(document).ready(function() {
          $('body').append('<script src="https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places&callback=getCurrentPickupLocation" async defer><\/script>');
     });
</script>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top