2009-08-18 18 views
43

¿Hay un evento que se activa cuando se cargan los archivos de JavaScript? El problema surgió porque YSlow recomienda mover los archivos JavaScript al final de la página. Esto significa que $(document).ready(function1) se activa antes de que se cargue el archivo js que contiene el código para function1.¿Cómo detectar si los archivos javascript están cargados?

¿Cómo evitar este tipo de situaciones?

Respuesta

65

No tengo una referencia a mano, pero las etiquetas de script se procesan en orden, por lo que si coloca $(document).ready(function1) en una etiqueta de script después de las etiquetas de script que definen function1, etc., debería ser bueno ir.

<script type='text/javascript' src='...'></script> 
<script type='text/javascript' src='...'></script> 
<script type='text/javascript'> 
$(document).ready(function1); 
</script> 

Por supuesto, otra posibilidad sería asegurarse de que está utilizando sólo una etiqueta de script, en total, mediante la combinación de archivos como parte de su proceso de construcción. (A menos que esté cargando los otros desde un CDN en algún lugar). Eso también ayudará a mejorar la velocidad percibida de su página.

EDIT: me di cuenta de que en realidad no respondí tu pregunta: No creo que haya un evento de navegador cruzado que se dispare, no.Hay si trabajas lo suficiente, mira a continuación. Puede probar para los símbolos y utilizar setTimeout para reprogramar:

<script type='text/javascript'> 
function fireWhenReady() { 
    if (typeof function1 != 'undefined') { 
     function1(); 
    } 
    else { 
     setTimeout(fireWhenReady, 100); 
    } 
} 
$(document).ready(fireWhenReady); 
</script> 

... pero no debería tener que hacer eso si usted consigue su pedido etiqueta script correcto.


Actualización: Puede obtener notificaciones de carga de script elementos que se agregan a la página dinámicamente si lo desea. Para conseguir el apoyo del navegador amplio, que tiene que hacer dos cosas diferentes, sino como una técnica combinada funciona esto:

function loadScript(path, callback) { 

    var done = false; 
    var scr = document.createElement('script'); 

    scr.onload = handleLoad; 
    scr.onreadystatechange = handleReadyStateChange; 
    scr.onerror = handleError; 
    scr.src = path; 
    document.body.appendChild(scr); 

    function handleLoad() { 
     if (!done) { 
      done = true; 
      callback(path, "ok"); 
     } 
    } 

    function handleReadyStateChange() { 
     var state; 

     if (!done) { 
      state = scr.readyState; 
      if (state === "complete") { 
       handleLoad(); 
      } 
     } 
    } 
    function handleError() { 
     if (!done) { 
      done = true; 
      callback(path, "error"); 
     } 
    } 
} 

En mi experiencia, la notificación de error (onerror) no es fiable al 100% multi-navegador. También tenga en cuenta que algunos navegadores harán ambos mecanismos, de ahí la variable done para evitar notificaciones duplicadas.

+0

Gracias por su respuesta, pero para mí parece extraño de alguna manera, ¿por qué debería colocar $ (documento). Listo (...) después de la etiqueta

0

Cambie el orden de carga de sus scripts para que se haya definido function1 antes de usarlo en ready devolución de llamada.

Plus Siempre me pareció mejor definir la devolución de llamada ready como un método anónimo y luego nombrar uno.

+0

Bueno, no es posible definirlo antes porque está en el archivo javascript. –

+0

Puede incluir el archivo con la definición 'function1' primero y luego incluir otro archivo que use esa función. El punto es que no se puede simplemente agregar archivos de script en orden aleatorio. – RaYell

5

Cuando dicen "La parte inferior de la página" literalmente no significan el final: significan justo antes de la etiqueta de cierre </body>. Coloque allí sus scripts y se cargarán antes del evento DOMReady; colóquelos luego y el DOM estará listo antes de que se carguen (porque está completo cuando se analiza la etiqueta de cierre </html>), que, como ha encontrado, no funcionará.

Si se pregunta cómo sé que esto es lo que quieren decir: he trabajado en Yahoo! y ponemos nuestros scripts justo antes de la etiqueta </body> :-)

EDITAR: también, ver T.J. Respuesta de Crowder y asegúrese de tener las cosas en el orden correcto.

0

Me gusta T.J.wrote: el orden es definido (al menos es secuencial cuando su navegador es aproximadamente para ejecutar cualquier JavaScript, incluso si puede descargar los scripts en paralelo de alguna manera). Sin embargo, como aparentemente tiene problemas, tal vez esté utilizando bibliotecas de JavaScript de terceros que producen 404 Not Found o timeout? Si es así, lea Best way to use Google’s hosted jQuery, but fall back to my hosted library on Google fail.

1

Siempre realizo una llamada desde el final de los archivos de JavaScript para registrar su carga y solía funcionar perfecto para todos los navegadores.

Ejemplo: Tengo un index.htm, Js1.js y Js2.js. Agrego la función IAmReady (Id) en el encabezado index.htm y lo llamo con los parámetros 1 y 2 desde el final de los archivos, Js1 y Js2 respectivamente. La función IAmReady tendrá una lógica para ejecutar el código de arranque una vez que recibe dos llamadas (almacenando el número de llamadas en una variable estática/global) de los dos archivos js.

1

Además de T. J @. Crowder respuesta 's, he añadido un lazo externo recursivo que permite iterar a través de todos los scripts en una matriz y luego ejecutar una función una vez que todos los scripts se cargan:

loadList([array of scripts], 0, function(){// do your post-scriptload stuff}) 

function loadList(list, i, callback) 
{ 
    { 
     loadScript(list[i], function() 
     { 
      if(i < list.length-1) 
      { 
       loadList(list, i+1, callback); 
      } 
      else 
      { 
       callback(); 
      } 
     }) 
    } 
} 

Por supuesto se puede hacer una envoltorio para deshacerse del '0' si te gusta:

function prettyLoadList(list, callback) 
{ 
    loadList(list, 0, callback); 
} 

Nice work @TJ Crowder - Me encogí de dolor ante el "solo agregue un par de segundos de retraso antes de ejecutar la devolución de llamada" que vi en otros hilos.

Cuestiones relacionadas