script otro llamar funcion externo ejemplo desde con cargar archivo javascript jquery html promise

javascript - otro - Cómo incluir archivos js múltiples usando el método jQuery $.getScript()



llamar javascript desde html (17)

Estoy tratando de incluir dinámicamente archivos javascript en mi archivo js. Hice algunas investigaciones al respecto y descubrí que el método jQuery $ .getScript () sería un camino deseado.

// jQuery $.getScript(''/path/to/imported/script.js'', function() { // script is now loaded and executed. // put your dependent JS here. // what if the JS code is dependent on multiple JS files? });

Pero me pregunto si este método puede cargar varios scripts a la vez. Por qué lo estoy preguntando es porque a veces mi archivo javascript depende de más de un archivo js.

Gracias de antemano.


Añadir scripts con async = falso

Aquí hay un enfoque diferente, pero muy simple. Para cargar varios scripts, simplemente puede agregarlos al cuerpo.

  • Los carga de forma asíncrona, porque así es como los navegadores optimizan la carga de la página
  • Ejecuta scripts en orden, porque así es como los navegadores analizan las etiquetas HTML
  • No hay necesidad de devolución de llamada, porque los scripts se ejecutan en orden. Simplemente agregue otro script, y se ejecutará después de los otros scripts

Más información aquí: https://www.html5rocks.com/en/tutorials/speed/script-loading/

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


La respuesta es

Puede utilizar promesas con getScript() y esperar hasta que se carguen todos los scripts, algo como:

$.when( $.getScript( "/mypath/myscript1.js" ), $.getScript( "/mypath/myscript2.js" ), $.getScript( "/mypath/myscript3.js" ), $.Deferred(function( deferred ){ $( deferred.resolve ); }) ).done(function(){ //place your code here, the scripts are all loaded });

FIDDLE

OTRA FIDDLE

En el código anterior, agregar un Deferred y resolverlo dentro de $() es como colocar cualquier otra función dentro de una llamada de jQuery, como $(func) , es lo mismo que

$(function() { func(); });

es decir, espera que el DOM esté listo, por lo que en el ejemplo anterior $.when espera a que se carguen todos los scripts y que el DOM esté listo debido a la llamada $.Deferred que se resuelve en la devolución de llamada lista para el DOM.

Para un uso más genérico, una función práctica

Una función de utilidad que acepta cualquier matriz de scripts podría crearse así:

$.getMultiScripts = function(arr, path) { var _arr = $.map(arr, function(scr) { return $.getScript( (path||"") + scr ); }); _arr.push($.Deferred(function( deferred ){ $( deferred.resolve ); })); return $.when.apply($, _arr); }

que se puede usar así

var script_arr = [ ''myscript1.js'', ''myscript2.js'', ''myscript3.js'' ]; $.getMultiScripts(script_arr, ''/mypath/'').done(function() { // all scripts loaded });

donde la ruta se agregará a todas las secuencias de comandos, y también es opcional, lo que significa que si la matriz contiene la URL completa, también se podría hacer, y dejar de lado la ruta todos juntos.

$.getMultiScripts(script_arr).done(function() { ...

Argumentos, errores, etc.

Como nota adicional, tenga en cuenta que la devolución de llamada done contendrá una cantidad de argumentos que coincidan con los scripts pasados, cada argumento que represente una matriz que contenga la respuesta

$.getMultiScripts(script_arr).done(function(response1, response2, response3) { ...

donde cada matriz contendrá algo así como [content_of_file_loaded, status, xhr_object] . Por lo general, no necesitamos acceder a esos argumentos, ya que los scripts se cargarán automáticamente de todos modos, y la mayoría de las veces la devolución de llamada done es lo único que queremos saber para saber que todos los scripts se han cargado, solo lo estoy agregando para integridad, y para las raras ocasiones en que se necesita acceder al texto real del archivo cargado, o cuando se necesita acceder a cada objeto XHR o algo similar.

Además, si alguno de los scripts no se carga, se llamará al controlador de fallas y no se cargarán los scripts posteriores.

$.getMultiScripts(script_arr).done(function() { // all done }).fail(function(error) { // one or more scripts failed to load }).always(function() { // always called, both on success and error });


A veces es necesario cargar scripts en un orden específico. Por ejemplo, jQuery debe estar cargado antes de jQuery UI. La mayoría de los ejemplos en esta página cargan scripts en paralelo (asincrónicamente) lo que significa que el orden de ejecución no está garantizado. Sin ordenar, el script y que depende de x podría romperse si ambos se cargan correctamente pero en orden incorrecto.

Propongo un enfoque híbrido que permite la carga secuencial de scripts dependientes + carga paralela opcional + objetos diferidos :

/* * loads scripts one-by-one using recursion * returns jQuery.Deferred */ function loadScripts(scripts) { var deferred = jQuery.Deferred(); function loadScript(i) { if (i < scripts.length) { jQuery.ajax({ url: scripts[i], dataType: "script", cache: true, success: function() { loadScript(i + 1); } }); } else { deferred.resolve(); } } loadScript(0); return deferred; } /* * example using serial and parallel download together */ // queue #1 - jquery ui and jquery ui i18n files var d1 = loadScripts([ "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js", "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/i18n/jquery-ui-i18n.min.js" ]).done(function() { jQuery("#datepicker1").datepicker(jQuery.datepicker.regional.fr); }); // queue #2 - jquery cycle2 plugin and tile effect plugin var d2 = loadScripts([ "https://cdn.rawgit.com/malsup/cycle2/2.1.6/build/jquery.cycle2.min.js", "https://cdn.rawgit.com/malsup/cycle2/2.1.6/build/plugin/jquery.cycle2.tile.min.js" ]).done(function() { jQuery("#slideshow1").cycle({ fx: "tileBlind", log: false }); }); // trigger a callback when all queues are complete jQuery.when(d1, d2).done(function() { console.log("All scripts loaded"); });

@import url("https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/blitzer/jquery-ui.min.css"); #slideshow1 { position: relative; z-index: 1; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <p><input id="datepicker1"></p> <div id="slideshow1"> <img src="https://dummyimage.com/300x100/FC0/000"> <img src="https://dummyimage.com/300x100/0CF/000"> <img src="https://dummyimage.com/300x100/CF0/000"> </div>

Los scripts en ambas colas se descargarán en paralelo, sin embargo, los scripts en cada cola se descargarán en secuencia, asegurando la ejecución ordenada. Tabla de cascadas:


Aquí está la respuesta usando Maciej Sawicki e implementando Promise como devolución de llamada:

function loadScripts(urls, path) { return new Promise(function(resolve) { urls.forEach(function(src, i) { let script = document.createElement(''script''); script.type = ''text/javascript''; script.src = (path || "") + src; script.async = false; // If last script, bind the callback event to resolve if(i == urls.length-1) { // Multiple binding for browser compatibility script.onreadystatechange = resolve; script.onload = resolve; } // Fire the loading document.body.appendChild(script); }); }); }

Utilizar:

let JSDependencies = ["jquery.js", "LibraryNeedingJquery.js", "ParametersNeedingLibrary.js"]; loadScripts(JSDependencies,''JavaScript/'').then(taskNeedingParameters);

Todos los archivos Javascript se descargan lo antes posible y se ejecutan en el orden indicado. Luego se llama a taskNeedingParameters .


Carga n scripts uno por uno (es útil si, por ejemplo, el segundo archivo necesita el primero):

(function self(a,cb,i){ i = i || 0; cb = cb || function(){}; if(i==a.length)return cb(); $.getScript(a[i++],self.bind(0,a,cb,i)); })([''list'',''of'',''script'',''urls''],function(){console.log(''done'')});


Cargue la siguiente secuencia de comandos necesaria en la devolución de llamada de la anterior, como:

$.getScript(''scripta.js'', function() { $.getScript(''scriptb.js'', function() { // run script that depends on scripta.js and scriptb.js }); });


Esta función se asegurará de que se carga un archivo después de que el archivo de dependencia se haya cargado por completo. Solo necesita proporcionar los archivos en una secuencia teniendo en cuenta las dependencias de otros archivos.

function loadFiles(files, fn) { if (!files.length) { files = []; } var head = document.head || document.getElementsByTagName(''head'')[0]; function loadFile(index) { if (files.length > index) { var fileref = document.createElement(''script''); fileref.setAttribute("type", "text/javascript"); fileref.setAttribute("src", files[index]); head.appendChild(fileref); index = index + 1; // Used to call a callback function fileref.onload = function () { loadFile(index); } } else if(fn){ fn(); } } loadFile(0); }


Esto funciona para mí:

function getScripts(scripts) { var prArr = []; scripts.forEach(function(script) { (function(script){ prArr .push(new Promise(function(resolve){ $.getScript(script, function () { resolve(); }); })); })(script); }); return Promise.all(prArr, function(){ return true; }); }

Y úsala:

var jsarr = [''script1.js'',''script2.js'']; getScripts(jsarr).then(function(){ ... });


Gran respuesta, adeneo.

Me llevó algo de tiempo descubrir cómo hacer que tu respuesta sea más genérica (para poder cargar una serie de scripts definidos por código). Se llama a la devolución de llamada cuando todas las secuencias de comandos se han cargado y ejecutado. Aquí está mi solución:

function loadMultipleScripts(scripts, callback){ var array = []; scripts.forEach(function(script){ array.push($.getScript( script )) }); array.push($.Deferred(function( deferred ){ $( deferred.resolve ); })); $.when.apply($, array).done(function(){ if (callback){ callback(); } }); }


Hay un complemento que extiende el método getScript de jQuery. Permite la carga asíncrona y sincrónica y utiliza el mecanismo de caché de jQuery. Divulgación completa, escribí esto. Por favor, siéntase libre de contribuir si encuentra un mejor método.

https://github.com/hudsonfoo/jquery-getscripts


Implementé una función simple para cargar varios scripts en paralelo:

Función

function getScripts(scripts, callback) { var progress = 0; scripts.forEach(function(script) { $.getScript(script, function () { if (++progress == scripts.length) callback(); }); }); }

Uso

getScripts(["script1.js", "script2.js"], function () { // do something... });


Lo que está buscando es un cargador compatible con AMD (como require.js).

http://requirejs.org/

http://requirejs.org/docs/whyamd.html

Hay muchos buenos de código abierto si lo buscas. Básicamente esto le permite definir un módulo de código, y si depende de otros módulos de código, esperará hasta que esos módulos hayan terminado de descargarse antes de proceder a la ejecución. De esta manera puede cargar 10 módulos de forma asíncrona y no debería haber problemas, incluso si uno depende de algunos de los otros para ejecutar.


Me encontré con una serie de problemas con la carga de secuencias de comandos múltiples inculding un problema con (al menos en Chrome) mismo dominio de carga de secuencias de comandos que no se ejecutan en realidad después de ser cargados con éxito por Ajax, donde Cross Domain funciona perfectamente bien! :(

La respuesta seleccionada a la pregunta original no funciona de manera confiable.

Después de muchas iteraciones, aquí está mi respuesta final a getScript (s) y cargando asíncronamente múltiples scripts en un orden estricto específico con la opción callback cargada por script y la devolución de llamada completa al finalizar, probado en jQuery 2.1+ y versiones modernas de Chrome, Firefox más el abandonado Internet Explorer.

Mi caso de prueba fue cargar archivos para un render webGL THREE.JS y luego iniciar el script de renderización cuando TRES global estuvo disponible usando una verificación de intervalo pasada a una llamada de función anónima a onComplete.

La función de prototipo (getScripts)

function getScripts( scripts, onScript, onComplete ) { this.async = true; this.cache = false; this.data = null; this.complete = function () { $.scriptHandler.loaded(); }; this.scripts = scripts; this.onScript = onScript; this.onComplete = onComplete; this.total = scripts.length; this.progress = 0; }; getScripts.prototype.fetch = function() { $.scriptHandler = this; var src = this.scripts[ this.progress ]; console.log(''%cFetching %s'',''color:#ffbc2e;'', src); $.ajax({ crossDomain:true, async:this.async, cache:this.cache, type:''GET'', url: src, data:this.data, statusCode: { 200: this.complete }, dataType:''script'' }); }; getScripts.prototype.loaded = function () { this.progress++; if( this.progress >= this.total ) { if(this.onComplete) this.onComplete(); } else { this.fetch(); }; if(this.onScript) this.onScript(); };

Cómo utilizar

var scripts = new getScripts( [''script1.js'',''script2.js'',''script.js''], function() { /* Optional - Executed each time a script has loaded (Use for Progress updates?) */ }, function () { /* Optional - Executed when the entire list of scripts has been loaded */ } ); scripts.fetch();

La función es la misma que encontré al usar Deferred (¿Obsoleto ahora?), When, Success & Complete en mis ensayos NO es 100% confiable!?, De ahí esta función y el uso de statusCode por ejemplo.

Es posible que desee agregar un comportamiento de manejo de errores / fallas si lo desea.


Puede utilizar el método $.when al intentar la siguiente función:

function loadScripts(scripts) { scripts.forEach(function (item, i) { item = $.getScript(item); }); return $.when.apply($, scripts); }

Esta función se usaría así:

loadScripts([''path/to/script-a.js'', ''path/to/script-b.js'']).done(function (respA, respB) { // both scripts are loaded; do something funny });

Esa es la forma de usar Promises y tener un mínimo de gastos generales.


Utilice yepnope.js o Modernizr (que incluye yepnope.js como Modernizr.load ).

ACTUALIZAR

Solo para seguir, aquí hay un buen equivalente de lo que tienes actualmente usando yepnope, mostrando dependencias en múltiples scripts:

yepnope({ load: [''script1.js'', ''script2.js'', ''script3.js''], complete: function () { // all the scripts have loaded, do whatever you want here } });


Versión más breve de la respuesta integral de Andrew Marc Newton anterior. Éste no verifica el código de estado para verificar el éxito, lo que debe hacer para evitar el comportamiento de UI no definido.

Este fue para un sistema molesto en el que podía garantizar jQuery pero ningún otro incluye, por lo que quería una técnica lo suficientemente corta como para no ser arrastrada a un script externo si se lo forzaba. (Podría hacerlo aún más corto pasando el índice 0 a la primera llamada "recursiva" pero la fuerza de los hábitos de estilo me hizo agregar el azúcar).

También estoy asignando la lista de dependencia a un nombre de módulo, por lo que este bloque se puede incluir en cualquier lugar que necesite "módulo1" y los scripts y la inicialización dependiente solo se incluirán / ejecutarán una vez (puede registrar el index en la devolución de llamada y ver un solo conjunto ordenado de ejecución de solicitudes AJAX)

if(typeof(__loaders) == ''undefined'') __loaders = {}; if(typeof(__loaders.module1) == ''undefined'') { __loaders.module1 = false; var dependencies = []; dependencies.push(''/scripts/loadmefirst.js''); dependencies.push(''/scripts/loadmenext.js''); dependencies.push(''/scripts/loadmelast.js''); var getScriptChain = function(chain, index) { if(typeof(index) == ''undefined'') index = 0; $.getScript(chain[index], function() { if(index == chain.length - 1) { __loaders.module1 = true; /* !!! Do your initialization of dependent stuff here !!! */ } else getScriptChain(chain, index + 1); } ); }; getScriptChain(dependencies); }


en función de la respuesta de @adeneo anterior: combinación de carga de archivos css y js

alguna sugerencia para mejoras?

// Usage //$.getMultiResources([''script-1.js'',''style-1.css''], ''assets/somePath/'') // .done(function () {}) // .fail(function (error) {}) // .always(function () {}); (function ($) { $.getMultiResources = function (arr, pathOptional, cache) { cache = (typeof cache === ''undefined'') ? true : cache; var _arr = $.map(arr, function (src) { var srcpath = (pathOptional || '''') + src; if (/.css$/i.test(srcpath)) { return $.ajax({ type: ''GET'', url: srcpath, dataType: ''text'', cache: cache, success: function () { $(''<link>'', { rel: ''stylesheet'', type: ''text/css'', ''href'': srcpath }).appendTo(''head''); } }); } else { return $.ajax({ type: ''GET'', url: srcpath, dataType: ''script'', cache: cache }); } }); // _arr.push($.Deferred(function (deferred) { $(deferred.resolve); })); // return $.when.apply($, _arr); }; })(jQuery);