2009-12-18 18 views
25

Uso la carga dinámica de scripts para reducir la duración de la carga de la página inicial. Para garantizar que las funciones y objetos definidos por un script sean accesibles, necesito asegurarme de que el script se haya cargado por completo.¿Se puede confiar en script.readyState para detectar el final de la carga del script dinámico?

He desarrollado my own Javascript library para este fin, y así investigué bastante sobre el tema, estudiando cómo se hace en diferentes bibliotecas. Durante una discusión en relación con este tema, Kyle Simpson, el autor de LABjs, declaró que:

LABjs (y muchos otros cargadores) Conjunto tanto "onload" y "onreadystatechange" en todos los elementos del guión, sabiendo que algunos navegadores se disparará una, y algunos dispararán la otra ...

puede encontrar un ejemplo de esto en the current version of jQuery as of this writing, v1.3.2:

// Attach handlers for all browsers 
script.onload = script.onreadystatechange = function(){ 
    if (!done && (!this.readyState || 
    this.readyState == "loaded" || this.readyState == "complete")) { 
     done = true; 
     success(); 
     complete(); 

     // Handle memory leak in IE 
     script.onload = script.onreadystatechange = null; 
     head.removeChild(script); 
    } 
}; 

Ese es el estado de la técnica, pero durante el análisis de un comportamiento extraño en Opera 9.64, llegué a la conclusión de que, utilizando esta técnica, la devolución de llamada de carga se activó demasiado pronto.

Voy a publicar mis propios resultados en respuesta a esta pregunta, y me gustaría recabar más pruebas y comentarios de la comunidad.

+0

Cualquiera encuentra el código actual en la rama jQuery 1.x-master? Parece que dejaron de usar '.onreadystatechange' y' .onload' y los reemplazaron con promesas? [Clicky] (https://github.com/jquery/jquery/blob/1.x-master/src/ajax.js) – Campbeln

Respuesta

7

En Opera, no se puede confiar en la propiedad script.readyState. Por ejemplo, el readyState "cargado" puede activarse antes de que el script se ejecute en Opera 9.64.

Realicé the same test en Opera 9.64 y Opera 10, con diferentes resultados.

En Opera 9.64, el controlador onreadystatechange se activa dos veces, una vez antes y una vez que se ejecuta la secuencia de comandos. La propiedad readyState se "carga" en ambos casos, lo que significa que este valor no se puede confiar para detectar el final de la carga de la escritura:

# Fri Dec 18 2009 17:54:43 GMT+0100 
# Opera/9.64 (Windows NT 5.1; U; en) Presto/2.1.1 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
readystatechange: loaded 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 
readystatechange: loaded 

En Opera 10, el controlador de onreadystatechange todavía es despedido dos veces con el valor " cargados", pero en ambas ocasiones después de la secuencia de comandos corrieron:

# Fri Dec 18 2009 18:09:58 GMT+0100 
# Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.10 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 
readystatechange: loaded 
readystatechange: loaded 

Estas diferentes comportamientos indican que onreadystatechange no es un método fiable para detectar el final de una secuencia de comandos de carga en Opera. Dado que Opera también es compatible con el oyente de carga, este otro mecanismo debería utilizarse en su lugar.

Según los resultados de estas pruebas, onreadystatechange solo se debe utilizar para detectar el final de la carga del script en Internet Explorer, y no se debe configurar en otros navegadores.

+0

Por lo menos, puede ignorar el primer evento. –

+2

@Justin Johnson que parece incómodo, ¿contarás los eventos "cargados", pero solo en Opera? –

3

En Firefox, Safari y Chrome, se llama al controlador onreadystatechange nevers.

he creado un caso de prueba corta, la creación de un guión dinámico con sólo el conjunto manipulador onreadystatechange:

<script type="text/javascript" language="javascript"> 
bezen.log.info(new Date(),true); 
bezen.log.info(navigator.userAgent,true); 

// Activate logs 
bezen.log.on(); 
bezen.log.info('Test for script.readyState behavior started'); 

var script = document.createElement('script'); 
script.src = 'test1.js'; 
script.onreadystatechange = function(){ 
    bezen.log.info('readystatechange: '+script.readyState); 
}; 
document.body.appendChild(script); 
bezen.log.info('Added script with onreadystatechange handler'); 
</script> 

He realizado la prueba en un archivo local en Firefox 2, Firefox 3, Firefox 3.5, Safari 3, Safari 4 y Chrome 3, y obtuvieron resultados similares (en este caso los registros grabados en FF 3.5):

Fri Dec 18 2009 17:53:58 GMT+0100 
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 

El onreadystatechange nunca se llama. En estos navegadores, solo el escucha de onload es útil para detectar el final de la carga de un script, el onreadystatechange no es necesario.

1

En Internet Explorer, el controlador onreadystatechange se desencadena como se esperaba después del final del script.

que realiza la same test en Internet Explorer 6, Internet Explorer 7 e Internet Explorer 8, con resultados similares en estos tres navegadores (en este caso los registros guardados en Internet Explorer 6):

Fri Dec 18 18:14:51 UTC+0100 2009 
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729) 
Test for script.readyState behavior started 
Added script with onreadystatechange handler 
test1.js: Start 
test1.js: Start of closure 
test1.js: End of closure 
readystatechange: complete 

Aquí, con una prueba utilizando un archivo local, el readyState siempre está "completo", y seguía siendo el mismo después de varias páginas de actualización.

Sin embargo, como se indica en this post by Nicholas C. Zakas, también puede observar "cargado" y "completo", o simplemente "cargado", en diferentes circunstancias.

1

He encontrado que Internet Explorer (prueba en 9) NO SIEMPRE tiene su script listo cuando readyState === 'loaded'. He tenido éxito usando este controlador de eventos (en 9 por supuesto) onactivate. Estaba jalando mi pelo antes.

0

Resultados similares en Chrome.

no toma onready ...

Sólo proceso de carga y onerror.

Cuestiones relacionadas