2011-04-30 23 views
12

en un clic, lo siguiente que se carga:getScript - Como sólo para llamar si no se ha llamado

$.getScript('/javascripts/contacts.js'); 

¿Cómo puedo escribir un comunicado que dice

si el getScript anterior ya está cargado hacer X ,, si no está cargado, ¿Y ...?

Gracias

+0

¿Por qué quiere hacer esto? ¿Estás hablando de almacenamiento en caché? ¿o estás hablando de evaluación condicional? – geocar

+0

gracias por preguntar Quiero hacer esto ya que mi aplicación tiene varios módulos, por así decirlo. Contactos, tareas, etc. No quiero cargar todos los JS a menos que sea necesario. Entonces, si el usuario hace clic en Contactos, entonces quiero cargar el archivo contacts.js, pero si hacen clic y luego vuelvo a hacer clic en Contactos. No quiero recargarlo. ? – AnApprentice

+3

Su navegador ya lo hará debido al almacenamiento en caché. – geocar

Respuesta

11
var gotContacts = 0; 
function getContacts(){ 
    if (!gotContacts){ 
     $.getScript('/javascripts/contacts.js', function() { 
      gotContacts = 1; 
      doSomethingWithContacts(); 
     }); 
    }else{ 
     doSomethingWithContacts(); 
    } 
} 
+2

Si existe el peligro de que se produzcan varias solicitudes en el tiempo que tarda el script en obtenerse, también puede agregar un marcador pendiente ('getContacts') antes de getScript para que solo se active la primera solicitud. Si no lo hace, puede terminar con la secuencia de comandos que se carga en el DOM varias veces. – notreadbyhumans

-2

No haga esto; no trate la etiqueta <script> como su compilador que carga su código fuente. En su lugar, concatene todo su código fuente usando un javascript minifier, y solo presione el servidor una vez.

Cargar un archivo 4k es mejor que cargar cuatro archivos 1k, y el minificador probablemente puede hacer un mejor trabajo que eso. No deberías necesitarlo de todos modos, tu navegador está almacenando en caché estos módulos de todos modos y, a menos que estropees la configuración de tu servidor, hará lo correcto.

Si realmente desea continuar, primer vistazo a la demanda de carga de bibliotecas de Javascript como Ensure, o Ajile o Dojo, o JSAN. Al menos entonces, no estás reinventando la rueda.

¿Todavía quieres hacerlo tú mismo? Puede verificar algo que contacts.js hace, o usar una variable para comprobar si lo ha hecho. Si contacts.js tiene algo como esto en él:

function ContactsLoaded(){...} 

que puede hacer:

if(typeof ContactsLoaded=='undefined')$.getScript('contacts.js'); 

Alternativamente, puede establecer usted mismo y hacer una función del cargador:

function getScriptOnce(f){ 
    var a=getScriptOnce; 
    if(typeof a[f]=='undefined')$.getScript(f); 
    a[f]=true; 
} 
+1

¿Por qué utilizar carga a petición en lugar de concat? Digamos que tienes un gordo 30K (min) js alimentando un plugin. Es probable que ese usuario se encuentre con este complemento mientras navega, es de 1 a 20. ¿Crees que debería precargarlo? ¿No crees que la carga a pedido tiene más sentido? – Jeffz

+0

Su punto es bueno, pero esta pregunta se trata de módulos independientes de carga de demanda (ver los comentarios en la pregunta), lo que significa que la mayoría de los usuarios verán la mayoría de los módulos. Lo que sugieres puede resolverse con una carga cortés de un backend grueso y es * muy * fácil de hacer: solo incluye la etiqueta del script y deja que el navegador lo guarde en caché como lo haría normalmente. – geocar

+0

No te critiqué, solo hice un puntero (para todos los que leen) que cada herramienta (incluido el concat) debe elegirse teniendo en cuenta el trabajo. – Jeffz

6

Mi situación era diferente. Usé un menú para cargar contenido en un div usando jquery. Para evitar que haya demasiadas secuencias de comandos en la sección del encabezado, utilicé .getscript para cargar el archivo solo si se llamó a ese enlace. Aquí está la solución que surgió para evitar duplicados:

Primero creo una función que fue responsable de cargar el script. Esto es parte del archivo global.js en mi sitio y el archivo global.js está codificado en el encabezamiento:

var loadedScripts=new Array(); 

function loadScriptFiles(scriptArray){ 

    if($.isArray(scriptArray)){ 
     $.each(scriptArray, function(intIndex, objValue){ 
      if($.inArray(objValue, loadedScripts) < 0){ 
       $.getScript(objValue, function(){ 
        loadedScripts.push(objValue); 
       }); 
      } 
     }); 
    } 
    else{ 
      if($.inArray(script, loadedScripts) < 0){ 
       $.getScript(script, function(){ 
        loadedScripts.push(objValue); 
       }); 
      } 





    } 
} 

Esta toma dos tipos de cargas, ya sea una matriz o un único valor de la escritura. Si se trata de una matriz, recorre cada elemento y lo carga. Si no es una matriz, solo cargará un archivo. Verás esa parte en un minuto.

Piezas importantes: Ver He creado una matriz en el ámbito global (fuera de la función) llamado loadedScripts. Como es parte del archivo global.js, nunca se vuelve a cargar y se puede llamar desde cualquier lugar. Sin embargo, para nuestros propósitos, simplemente comprobar para ver si el nombre del script que se está cargando ya está en la matriz mediante:

if($.inArray(objValue, loadedScripts) < 0){ 

Dado que la función jQuery InArray devuelve -1 si no se encuentra el valor, sólo continuará si el el valor es menor que 0.Cualquier otra cosa significa que el valor está en la matriz.

Así es como se llama a la función que se utilizará. Coloque este código en cualquier lugar (lo puse en la parte superior) de la página dinámica que se invocará.

<script type="text/javascript"> 
    var scriptArray=new Array(); 
    scriptArray[0]="[REPLACE THIS WITH THE PATH TO THE JS FILE]"; 
    scriptArray[1]="[REPLACE THIS WITH THE PATH TO THE JS FILE]"; 
    loadScriptFiles(scriptArray); 
</script> 

Si lo hace correctamente, observará que solo se carga una vez.

3

He creado un plugin que hace casi exactamente lo que desea: $.getScriptOnce().

Si intenta cargar el mismo script dos o más veces, no cargará el script y devolverá falso.

Pero, básicamente, se define esta función alternativa de $.getScript()

(function($) { 
    $.getScriptOnce = function(url, successhandler) { 
     if ($.getScriptOnce.loaded.indexOf(url) === -1) { 
      $.getScriptOnce.loaded.push(url); 
      if (successhandler === undefined) { 
       return $.getScript(url); 
      } else { 
       return $.getScript(url, function(script, textStatus, jqXHR) { 
        successhandler(script, textStatus, jqXHR); 
       }); 
      } 
     } else { 
      return false; 
     } 

    }; 

    $.getScriptOnce.loaded = []; 

}(jQuery)); 

Y luego simplemente llaman $.getScriptOnce('yourFile.js')

+3

Este enlace está roto ... – rnevius

+0

Tienes razón, he eliminado este repositorio. Encontré el script y lo coloqué en un nuevo repositorio: https://github.com/RalonIT/jquery-getscriptonce y actualicé la respuesta. – Loran

+0

¿es esto compatible con IE? –

0

También escribí tal función. Puede probar con la pestaña de red en las herramientas Firebug o Chrome dev. Esto solo carga el mismo archivo una vez.

Preste atención para no descargar la segunda vez inmediatamente después de la anterior, porque la función simplemente asume que el archivo se cargó, después de llamar a la devolución de llamada, es decir, después de que el archivo se cargó correctamente.

var getScriptOnce = (function(url, callback) { 
 
    var scriptArray = []; //array of urls 
 
    return function (url, callback) { 
 
     //the global array doesn't have such url 
 
     if (scriptArray.indexOf(url) === -1){ 
 
      if (typeof callback === 'function') { 
 
       return $.getScript(url, function(script, textStatus, jqXHR) { 
 
        scriptArray.push(url); 
 
        callback(script, textStatus, jqXHR); 
 
       }); 
 
      } else { 
 
       return $.getScript(url, function(){ 
 
        scriptArray.push(url); 
 
       }); 
 
      } 
 
     } 
 
     //the file is already there, it does nothing 
 
     //to support as of jQuery 1.5 methods .done().fail() 
 
     else{ 
 
      return { 
 
       done: function() { 
 
        return { 
 
         fail: function() {} 
 
        }; 
 
       } 
 
      }; 
 
     } 
 
    } 
 
}()); 
 

 
/*#####################################################################*/ 
 
/*#####################################################################*/ 
 

 

 
//TEST - tries to load the same jQuery file twice 
 
var jQueryURL = "https://code.jquery.com/jquery-3.2.1.js"; 
 
console.log("Tries to load #1"); 
 
getScriptOnce(jQueryURL, function(){ 
 
    console.log("Loaded successfully #1") 
 
}); 
 

 
//waits 2 seconds and tries to load again 
 
window.setTimeout(function(){ 
 
    console.log("Tries to load #2"); 
 
    getScriptOnce(jQueryURL, function(){ 
 
    console.log("Loaded successfully #2"); 
 
    }); 
 
}, 2000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Cuestiones relacionadas