Pergunta

Como você pode carregar um arquivo JavaScript de maneira confiável e dinâmica?Isso pode ser usado para implementar um módulo ou componente que, quando 'inicializado', o componente carregará dinamicamente todos os scripts da biblioteca JavaScript necessários sob demanda.

O cliente que usa o componente não é obrigado a carregar todos os arquivos de script da biblioteca (e inserir manualmente <script> tags em sua página web) que implementam este componente - apenas o arquivo de script do componente 'principal'.

Como as principais bibliotecas JavaScript conseguem isso (Protótipo, jQuery, etc.)? Essas ferramentas mesclam vários arquivos JavaScript em uma única versão redistribuível de 'construção' de um arquivo de script?Ou eles fazem algum carregamento dinâmico de scripts auxiliares de 'biblioteca'?

Uma adição a esta pergunta: existe uma maneira de lidar com o evento após o carregamento de um arquivo JavaScript incluído dinamicamente? O protótipo tem document.observe para eventos em todo o documento.Exemplo:

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

Quais são os eventos disponíveis para um elemento de script?

Foi útil?

Solução

Você pode escrever tags de script dinâmicas (usando Protótipo):

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

O problema aqui é que não sabemos quando o arquivo de script externo está totalmente carregado.

Muitas vezes queremos nosso código dependente na próxima linha e gostamos de escrever algo como:

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

Existe uma maneira inteligente de injetar dependências de script sem a necessidade de retornos de chamada.Você simplesmente precisa extrair o script por meio de um solicitação AJAX síncrona e avaliar o roteiro em nível global.

Se você usar Prototype, o método Script.load ficará assim:

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

Outras dicas

Não há importação/inclusão/exigência em javascript, mas existem duas maneiras principais de conseguir o que você deseja:

1 - Você pode carregá-lo com uma chamada AJAX e depois usar eval.

Esta é a maneira mais direta, mas é limitada ao seu domínio por causa das configurações de segurança do Javascript, e usar eval está abrindo a porta para bugs e hacks.

2 - Adicione uma tag de script com a URL do script no HTML.

Definitivamente o melhor caminho a percorrer.Você pode carregar o script até mesmo de um servidor externo, e ele fica limpo quando você usa o analisador do navegador para avaliar o código.Você pode colocar a tag no cabeçalho da página da web ou na parte inferior do corpo.

Ambas as soluções são discutidas e ilustradas aqui.

Agora, há um grande problema que você deve conhecer.Fazer isso implica que você carregue o código remotamente.Os navegadores modernos carregarão o arquivo e continuarão executando o script atual porque carregam tudo de forma assíncrona para melhorar o desempenho.

Isso significa que se você usar esses truques diretamente, não poderá usar o código recém-carregado na próxima linha após solicitar que ele seja carregado, porque ele ainda estará carregando.

POR EXEMPLO :my_lovely_script.js contém 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

Então você recarrega a página pressionando F5.E funciona!Confuso...

Então o que fazer sobre isso ?

Bem, você pode usar o hack que o autor sugere no link que lhe dei.Em resumo, para pessoas com pressa, ele usa en event para executar uma função de retorno de chamada quando o script é carregado.Assim você pode colocar todo o código usando a biblioteca remota na função de retorno de chamada.POR EXEMPLO :

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

Então você escreve o código que deseja usar APÓS o script ser carregado em uma função lambda:

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

Então você executa tudo isso:

loadScript("my_lovely_script.js", myPrettyCode);

OK, entendi.Mas é uma pena escrever tudo isso.

Bem, nesse caso, você pode usar como sempre o fantástico framework jQuery gratuito, que permite fazer exatamente a mesma coisa em uma linha:

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

Eu usei um versão muito menos complicada recentemente com 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>

Funcionou muito bem em todos os navegadores em que testei:IE6/7, Firefox, Safari, Ópera.

Atualizar: Versão sem 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>

Fiz basicamente a mesma coisa que você fez com Adam, mas com uma pequena modificação para ter certeza de que estava anexando à tag head para realizar o trabalho.Simplesmente criei uma função include (código abaixo) para lidar com arquivos script e css.

Esta função também verifica se o script ou arquivo CSS ainda não foi carregado dinamicamente.Ele não verifica valores codificados manualmente e pode ter havido uma maneira melhor de fazer isso, mas serviu ao 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 );
}

outra resposta incrível

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

Aqui está um exemplo de código que encontrei ...alguém tem uma maneira melhor?

  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 você já carregou o jQuery, você deve usar $.getScript.

Isso tem uma vantagem sobre as outras respostas aqui, pois você tem uma função de retorno de chamada integrada (para garantir que o script seja carregado antes da execução do código dependente) e pode controlar o cache.

alguém tem uma maneira melhor?

Acho que apenas adicionar o script ao corpo seria mais fácil do que adicioná-lo ao último nó da página.Que tal agora:

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

usei mais uma solução que encontrei na net...este está sob Creativecommons e verifica se a fonte foi incluída antes de chamar a função ...

você pode encontrar o arquivo aqui: 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);
    }
  }   
} 

Acabei de descobrir um ótimo recurso em YUI 3 (no momento em que este artigo foi escrito, disponível na versão prévia).Você pode inserir facilmente dependências em bibliotecas YUI e em módulos "externos" (o que você está procurando) sem muito código: Carregador YUI.

Também responde à sua segunda pergunta sobre a função que está sendo chamada assim que o módulo externo é carregado.

Exemplo:

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

Funcionou perfeitamente para mim e tem a vantagem de gerenciar dependências.Consulte a documentação do YUI para obter um exemplo com calendário YUI 2.

Se você quiser um SINCRONIZAR carregamento do script, você precisa adicionar o texto do script diretamente à tag HTML HEAD.Adicioná-lo como irá acionar um Assíncrono carregar.Para carregar o texto do script do arquivo externo de forma síncrona, use XHR.Abaixo um exemplo rápido (está usando partes de outras respostas neste e em outros posts):

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

A técnica que usamos no trabalho é solicitar o arquivo javascript usando uma solicitação AJAX e depois eval() o retorno.Se você estiver usando a biblioteca de protótipos, eles suportam essa funcionalidade na chamada Ajax.Request.

jquery resolveu isso para mim com sua função .append()- usei isso para carregar o pacote 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 - no cabeçalho do seu html/php/etc, depois de importar o jquery.js, você apenas incluiria este arquivo para carregar toda a sua biblioteca, anexando-o ao cabeçalho ...

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

Mantenha-o agradável, curto, simples e sustentável!:]

// 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 é simplesmente um pequeno exemplo funcional que poderia requerem funcionalidade de recursos adicionais para suporte total em qualquer plataforma (ou determinada).

Há um novo padrão ECMA proposto chamado importação dinâmica, recentemente incorporado ao Chrome e Safari.

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

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

Existem scripts projetados especificamente para essa finalidade.

simnope.js está integrado ao Modernizr e laboratório.js é uma versão mais otimizada (mas menos amigável).

Eu não recomendaria fazer isso por meio de uma grande biblioteca como jquery ou protótipo - porque um dos principais benefícios de um carregador de script é a capacidade de carregar scripts antecipadamente - você não deveria ter que esperar até que o jquery e todos os seus elementos dom sejam carregados antes executando uma verificação para ver se deseja carregar um script dinamicamente.

Eu escrevi um módulo simples que automatiza o trabalho de importação/inclusão de scripts de módulo em JavaScript.Experimente e, por favor, poupe alguns comentários!:) Para obter uma explicação detalhada do código, consulte esta postagem do 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
});

Estou perdido em todos esses exemplos, mas hoje precisei carregar um .js externo do meu .js principal e fiz isso:

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

Aqui é simples, com retorno de chamada e suporte ao 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');

});

Aqui está um exemplo simples de uma função para carregar arquivos JS.Pontos relevantes:

  • você não precisa do jQuery, então você pode usá-lo inicialmente para carregar também o arquivo jQuery.js
  • é assíncrono com retorno de chamada
  • garante o carregamento apenas uma vez, pois mantém um gabinete com o registro das urls carregadas, evitando assim o uso da rede
  • contrário ao jQuery $.ajax ou $.getScript você pode usar nonces, resolvendo assim problemas com CSP unsafe-inline.Basta usar a propriedade 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);
        }
    };
}();

Agora você usa simplesmente

getScriptOnce("url_of_your_JS_file.js");

Uma frase absurda, para quem pensa que carregar uma biblioteca js não deve demorar mais que uma linha 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 se o script que você deseja importar for um módulo, você pode usar o import(...) função.

todas as principais bibliotecas javascript, como jscript, protótipo, YUI, têm suporte para carregar arquivos de script.Por exemplo, no YUI, após carregar o núcleo você pode fazer o seguinte para carregar o controle de calendário

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

Eu sei que minha resposta está um pouco atrasada para esta pergunta, mas aqui está um ótimo artigo em www.html5rocks.com - Mergulhe profundamente nas águas turvas do carregamento de scripts .

Nesse artigo conclui-se que em relação ao suporte do navegador, a melhor forma de carregar dinamicamente o arquivo JavaScript sem bloquear a renderização do conteúdo é a seguinte:

Considerando que você tem quatro scripts chamados script1.js, script2.js, script3.js, script4.js então você pode fazer isso com aplicando assí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);
});

Agora, A especificação diz:Baixe juntos, execute em ordem assim que todos baixarem.

Firefox <3.6, Opera diz: Não tenho ideia do que é essa coisa “assíncrona”, mas acontece que executo scripts adicionados via JS na ordem em que são adicionados.

Safari 5.0 diz: Entendo “assíncrono”, mas não entendo defini-lo como “falso” com JS.Executarei seus scripts assim que eles chegarem, em qualquer ordem.

IE < 10 diz: Não tenho ideia sobre “async”, mas há uma solução alternativa usando “onreadystatechange”.

Todo o resto diz: Eu sou seu amigo, vamos fazer isso de acordo com as regras.

Agora, o código completo com solução alternativa para 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>');
  }
}

Alguns truques e minificação depois, são 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 assim...

<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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top