Pregunta

¿Cómo se puede cargar de forma fiable y dinámica un archivo JavaScript?Esto se puede usar para implementar un módulo o componente que, cuando se "inicializa", el componente cargará dinámicamente todos los scripts de la biblioteca JavaScript necesarios a pedido.

El cliente que utiliza el componente no necesita cargar todos los archivos de script de la biblioteca (e insertar manualmente <script> etiquetas en su página web) que implementan este componente, solo el archivo de secuencia de comandos del componente "principal".

¿Cómo logran esto las bibliotecas de JavaScript convencionales (Prototype, jQuery, etc.)? ¿Estas herramientas combinan varios archivos JavaScript en una única versión redistribuible de "compilación" de un archivo de script?¿O realizan alguna carga dinámica de scripts auxiliares de 'biblioteca'?

Una adición a esta pregunta: ¿Hay alguna manera de manejar el evento después de cargar un archivo JavaScript incluido dinámicamente? El prototipo tiene document.observe para eventos que abarcan todo el documento.Ejemplo:

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

¿Cuáles son los eventos disponibles para un elemento de script?

¿Fue útil?

Solución

Puede escribir etiquetas de script dinámicas (usando Prototipo):

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

El problema aquí es que no sabemos cuando el archivo de script externo está completamente cargado.

A menudo queremos que nuestro código dependiente esté en la siguiente línea y nos gusta escribir algo como:

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

Existe una forma inteligente de inyectar dependencias de scripts sin necesidad de devoluciones de llamada.Simplemente tienes que extraer el script a través de un solicitud AJAX sincrónica y evaluar el guión a nivel global.

Si usa Prototype, el método Script.load se ve así:

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

Otros consejos

No hay importación/inclusión/requisito en javascript, pero hay dos formas principales de lograr lo que desea:

1 - Puedes cargarlo con una llamada AJAX y luego usar eval.

Esta es la forma más sencilla, pero está limitada a su dominio debido a la configuración de seguridad de Javascript, y el uso de eval abre la puerta a errores y hacks.

2 - Agregue una etiqueta de secuencia de comandos con la URL del script en el HTML.

Definitivamente el mejor camino a seguir.Puede cargar el script incluso desde un servidor externo y está limpio ya que utiliza el analizador del navegador para evaluar el código.Puede colocar la etiqueta en el encabezado de la página web o en la parte inferior del cuerpo.

Ambas soluciones se analizan e ilustran aquí.

Ahora bien, hay un gran problema que debes conocer.Hacer eso implica que cargas el código de forma remota.Los navegadores web modernos cargarán el archivo y seguirán ejecutando el script actual porque cargan todo de forma asincrónica para mejorar el rendimiento.

Significa que si usa estos trucos directamente, no podrá usar el código recién cargado en la siguiente línea después de haber solicitado que se cargue, porque aún se estará cargando.

P.EJ :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

Luego recargas la página presionando F5.¡Y funciona!Confuso...

Entonces, ¿qué hacer al respecto?

Bueno, puedes usar el truco que sugiere el autor en el enlace que te di.En resumen, para las personas que tienen prisa, utiliza en event para ejecutar una función de devolución de llamada cuando se carga el script.Entonces puedes poner todo el código usando la biblioteca remota en la función de devolución de llamada.P.EJ :

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

Luego escribe el código que desea usar DESPUÉS de cargar el script en una función lambda:

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

Luego ejecutas todo eso:

loadScript("my_lovely_script.js", myPrettyCode);

Bien, lo tengo.Pero es doloroso escribir todo esto.

Bueno, en ese caso, puedes usar como siempre el fantástico framework gratuito jQuery, que te permite hacer exactamente lo mismo en una sola línea:

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

usé un versión mucho menos complicada recientemente 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>

Funcionó muy bien en todos los navegadores en los que lo probé:IE6/7, Firefox, Safari, Ópera.

Actualizar: Versión sin 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>

Básicamente hice lo mismo que tú hiciste con Adam, pero con una ligera modificación para asegurarme de agregar la etiqueta principal para realizar el trabajo.Simplemente creé una función de inclusión (código a continuación) para manejar archivos de script y css.

Esta función también verifica que el script o el archivo CSS no se haya cargado dinámicamente.No verifica los valores codificados manualmente y puede que haya habido una manera mejor de hacerlo, pero cumplió su propósito.

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

otra respuesta impresionante

$.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

Aquí hay un código de ejemplo que encontré...¿Alguien tiene una mejor manera?

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

Si ya tienes jQuery cargado, deberías usar $.getScript.

Esto tiene una ventaja sobre las otras respuestas aquí porque tiene una función de devolución de llamada incorporada (para garantizar que el script se cargue antes de que se ejecute el código dependiente) y puede controlar el almacenamiento en caché.

¿Alguien tiene una mejor manera?

Creo que simplemente agregar el script al cuerpo sería más fácil que agregarlo al último nodo de la página.Qué tal esto:

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

He usado otra solución que encontré en la red...este está bajo creativecommons y comprueba si la fuente se incluyó antes de llamar a la función ...

Puedes encontrar el archivo aquí: incluir.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);
    }
  }   
} 

Acabo de descubrir una gran característica en Yui 3 (en el momento de escribir este artículo, disponible en versión preliminar).Puede insertar fácilmente dependencias en las bibliotecas YUI y en los módulos "externos" (lo que está buscando) sin demasiado código: Cargador YUI.

También responde a su segunda pregunta sobre la función que se llama tan pronto como se carga el módulo externo.

Ejemplo:

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(...);
    }
});

Funcionó perfectamente para mí y tiene la ventaja de gestionar dependencias.Consulte la documentación de YUI para obtener una ejemplo con calendario YUI 2.

Si quieres un SINCRONIZACIÓN Al cargar el script, debe agregar el texto del script directamente a la etiqueta HTML HEAD.Agregarlo como activará un asíncrono carga.Para cargar texto de script desde un archivo externo de forma sincrónica, use XHR.A continuación se muestra un ejemplo rápido (utiliza partes de otras respuestas en esta y otras publicaciones):

/*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 técnica que usamos en el trabajo es solicitar el archivo javascript usando una solicitud AJAX y luego eval() la devolución.Si está utilizando la biblioteca de prototipos, admiten esta funcionalidad en su llamada Ajax.Request.

jquery resolvió esto por mí con su función .append()- usé esto para cargar el paquete jquery ui completo

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

Usar - en el encabezado de su html/php/etc, después de importar jquery.js, simplemente incluiría este archivo para cargarlo en toda su biblioteca y lo agregaría al encabezado...

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

¡Manténgalo agradable, breve, simple y fácil de mantener!:]

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

Este código es simplemente un breve ejemplo funcional que podría requieren funcionalidad de funciones adicionales para soporte completo en cualquier plataforma (o determinada).

Hay un nuevo estándar ECMA propuesto llamado importación dinámica, incorporado recientemente a Chrome y Safari.

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

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

Existen scripts que están diseñados específicamente para este propósito.

yepnope.js está integrado en Modernizr, y laboratorio.js es una versión más optimizada (pero menos fácil de usar).

No recomendaría hacer esto a través de una biblioteca grande como jquery o prototipo, porque uno de los principales beneficios de un cargador de scripts es la capacidad de cargar scripts temprano; no debería tener que esperar hasta que jquery y todos sus elementos dom se carguen antes. ejecutando una verificación para ver si desea cargar dinámicamente un script.

Escribí un módulo simple que automatiza el trabajo de importar/incluir scripts de módulos en JavaScript.¡Pruébalo y por favor deja algunos comentarios!:) Para obtener una explicación detallada del código, consulte esta publicación de 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
});

Estoy perdido en todos estos ejemplos, pero hoy necesitaba cargar un .js externo desde mi .js principal e hice esto:

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

Aquí es simple con devolución de llamada y soporte de 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');

});

Aquí un ejemplo simple de una función para cargar archivos JS.Puntos relevantes:

  • No necesitas jQuery, por lo que puedes usar esto inicialmente para cargar también el archivo jQuery.js.
  • es asíncrono con devolución de llamada
  • asegura que se cargue solo una vez, ya que mantiene un archivo adjunto con el registro de las URL cargadas, evitando así el uso de la red.
  • contrario a jQuery $.ajax o $.getScript puedes usar nonces, resolviendo así los problemas con CSP unsafe-inline.Solo usa la propiedad 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);
        }
    };
}();

Ahora lo usas simplemente por

getScriptOnce("url_of_your_JS_file.js");

Una frase absurda, para aquellos que piensan que cargar una biblioteca js no debería requerir más de una línea de código :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)});

Obviamente, si el script que desea importar es un módulo, puede utilizar el import(...) función.

Todas las principales bibliotecas de JavaScript, como jscript, prototipo y YUI, admiten la carga de archivos de script.Por ejemplo, en YUI, después de cargar el núcleo, puede hacer lo siguiente para cargar el control de 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();

Sé que mi respuesta llega un poco tarde a esta pregunta, pero aquí hay un gran artículo en www.html5rocks.com - Sumérgete en las turbias aguas de la carga de guiones .

En ese artículo se concluye que en lo que respecta a la compatibilidad del navegador, la mejor manera de cargar dinámicamente un archivo JavaScript sin bloquear la representación del contenido es la siguiente:

Teniendo en cuenta que tienes cuatro scripts nombrados script1.js, script2.js, script3.js, script4.js entonces puedes hacerlo con aplicando asíncrono = falso:

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

Ahora, Especificaciones dice:Descarguen juntos, ejecútenlos en orden tan pronto como se descarguen todos.

Firefox <3.6, Opera dice: No tengo idea de qué es esto de "asíncrono", pero resulta que ejecuto scripts agregados a través de JS en el orden en que se agregan.

Safari 5.0 dice: Entiendo "async", pero no entiendo configurarlo en "false" con JS.Ejecutaré tus scripts tan pronto como lleguen, en cualquier orden.

Es decir <10 dice: No tengo idea sobre "async", pero existe una solución alternativa usando "onreadystatechange".

Todo lo demás dice: Soy tu amigo, vamos a hacer esto según las reglas.

Ahora, el código completo con la solución 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>');
  }
}

Unos cuantos trucos y minificación después, son 362 bytes.

!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"
])

Algo como esto...

<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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top