type script ejemplos defer async javascript load-order

ejemplos - script type= text/javascript src=



cargar y ejecutar orden de scripts (2)

Hay tantas formas diferentes de incluir JavaScript en una página html. Conozco las siguientes opciones:

  • código en línea o cargado desde URI externo
  • incluido en la etiqueta <head> o <body> [ 1 , 2 ]
  • que no tiene ningún atributo, defer o async (solo scripts externos)
  • Incluido en una fuente estática o agregado dinámicamente por otros scripts (en diferentes estados de análisis, con diferentes métodos)

Sin contar los navegadores del disco duro, javascript: URIs y onEvent -attributes [ 3 ], ya hay 16 alternativas para ejecutar JS y estoy seguro de que olvidé algo.

No me preocupa tanto la carga rápida (paralela), tengo más curiosidad por el orden de ejecución (que puede depender de la orden de carga y la orden del documento ). ¿Existe una buena referencia (navegador cruzado) que cubra realmente todos los casos? Por ejemplo, http://www.websiteoptimization.com/speed/tweak/defer/ solo trata con 6 de ellos, y prueba la mayoría de los navegadores antiguos.

Como me temo que no hay, aquí está mi pregunta específica: tengo algunos scripts principales (externos) para la inicialización y la carga de scripts. Luego tengo dos scripts estáticos en línea al final del cuerpo. El primero permite que el cargador de scripts agregue dinámicamente otro elemento de script (que hace referencia a js externos) al cuerpo. El segundo de los guiones en línea estáticos quiere usar js del guión externo agregado. ¿Puede confiar en que el otro haya sido ejecutado (y por qué :-)?


El navegador ejecutará los scripts en el orden en que los encuentra. Si llama a un script externo, bloqueará la página hasta que el script se haya cargado y ejecutado.

Para probar este hecho:

// file: test.php sleep(10); die("alert(''Done!'');"); // HTML file: <script type="text/javascript" src="test.php"></script>

Los scripts agregados dinámicamente se ejecutan tan pronto como se agregan al documento.

Para probar este hecho:

<!DOCTYPE HTML> <html> <head> <title>Test</title> </head> <body> <script type="text/javascript"> var s = document.createElement(''script''); s.type = "text/javascript"; s.src = "link.js"; // file contains alert("hello!"); document.body.appendChild(s); alert("appended"); </script> <script type="text/javascript"> alert("final"); </script> </body> </html>

El orden de las alertas está "anexado" -> "¡Hola!" -> "final"

Si en un script intenta acceder a un elemento que aún no se ha alcanzado (ejemplo: <script>do something with #blah</script><div id="blah"></div> ), entonces obtendrá un error.

En general, sí, puede incluir scripts externos y luego acceder a sus funciones y variables, pero solo si sale de la etiqueta <script> actual y comienza una nueva.


Si no está cargando dinámicamente scripts o marcándolos como diferidos o asíncronos, entonces los scripts se cargan en el orden en que se encuentran en la página. No importa si es un script externo o un script en línea, se ejecutan en el orden en que se encuentran en la página. Los scripts en línea que vienen después de que se hayan guardado los scripts externos hasta que todos los scripts externos que vinieron antes de ellos se hayan cargado y ejecutado.

Los scripts asíncronos (independientemente de cómo se especifiquen como asíncronos) se cargan y ejecutan en un orden impredecible. El navegador los carga en paralelo y es libre de ejecutarlos en el orden que desee.

No hay un orden predecible entre múltiples cosas asincrónicas. Si uno necesita un orden predecible, entonces debería codificarse registrando notificaciones de carga desde los scripts asíncronos y secuenciando manualmente las llamadas de javascript cuando se carguen las cosas apropiadas.

Cuando se inserta dinámicamente una etiqueta de script, el comportamiento del orden de ejecución dependerá del navegador. Puedes ver cómo se comporta Firefox en este artículo de referencia . En pocas palabras, las versiones más recientes de Firefox predeterminan una etiqueta de script agregada dinámicamente a async, a menos que la etiqueta de script se haya configurado de otra manera.

Una etiqueta de script con async puede ejecutarse tan pronto como se carga. De hecho, el navegador puede pausar el analizador desde cualquier otra cosa que esté haciendo y ejecutar ese script. Por lo tanto, realmente puede funcionar en casi cualquier momento. Si el script se almacenó en caché, podría ejecutarse casi de inmediato. Si la secuencia de comandos tarda en cargarse, podría ejecutarse después de que se haya completado el analizador. Lo único que hay que recordar con async es que puede ejecutarse en cualquier momento y que el tiempo no es predecible.

Una etiqueta de script con defer espera hasta que se complete el analizador completo y luego ejecuta todos los scripts marcados con defer en el orden en que se encontraron. Esto le permite marcar varios scripts que dependen unos de otros como defer . Todos se pospondrán hasta después de que el analizador de documentos haya finalizado, pero se ejecutarán en el orden en que se encontraron conservando sus dependencias. Pienso en el defer que los scripts se colocan en una cola que se procesará una vez que el analizador haya terminado. Técnicamente, el navegador puede descargar los scripts en segundo plano en cualquier momento, pero no ejecutarán ni bloquearán el analizador hasta que el analizador haya terminado de analizar la página y analizar y ejecutar cualquier script en línea que no esté marcado como diferido o asíncrono.

Aquí hay una cita de ese artículo:

Los scripts insertados en el script se ejecutan de forma asíncrona en IE y WebKit, pero de forma síncrona en Opera y Firefox pre-4.0.

La parte relevante de la especificación HTML5 (para los navegadores compatibles más nuevos) está here . Hay mucho escrito allí sobre el comportamiento asíncrono. Obviamente, esta especificación no se aplica a los navegadores más antiguos (o a los navegadores mal confirmados) cuyo comportamiento probablemente tendría que probar para determinar.

Una cita de la especificación HTML5:

Luego, se debe seguir la primera de las siguientes opciones que describen la situación:

Si el elemento tiene un atributo src, y el elemento tiene un atributo diferido, y el elemento se ha marcado como "insertado en el analizador", y el elemento no tiene un atributo asíncrono. El elemento debe agregarse al final de la lista de Scripts que se ejecutarán cuando el documento haya terminado de analizar asociado con el documento del analizador que creó el elemento.

La tarea que el origen de la tarea de red coloca en la cola de tareas una vez que el algoritmo de recuperación ha finalizado debe establecer el indicador "listo para ser ejecutado por el analizador" del elemento. El analizador se encargará de ejecutar el script.

Si el elemento tiene un atributo src y el elemento se ha marcado como "insertado en el analizador", y el elemento no tiene un atributo asíncrono El elemento es la secuencia de comandos de bloqueo de análisis pendiente del documento del analizador que creó el elemento. (Solo puede haber un script por documento a la vez).

La tarea que el origen de la tarea de red coloca en la cola de tareas una vez que el algoritmo de recuperación ha finalizado debe establecer el indicador "listo para ser ejecutado por el analizador" del elemento. El analizador se encargará de ejecutar el script.

Si el elemento no tiene un atributo src, y el elemento se ha marcado como "insertado en el analizador", y el documento del analizador HTML o el analizador XML que creó el elemento del script tiene una hoja de estilo que está bloqueando los scripts El elemento es el pendiente del script de análisis de bloqueo del documento del analizador que creó el elemento. (Solo puede haber un script por documento a la vez).

Establezca el indicador "listo para ser ejecutado por el analizador" del elemento. El analizador se encargará de ejecutar el script.

Si el elemento tiene un atributo src, no tiene un atributo asíncrono y no tiene el conjunto de indicadores "forzar-asíncrono" El elemento debe agregarse al final de la lista de scripts que se ejecutarán en orden tan pronto como sea posible. con el Documento del elemento de secuencia de comandos en el momento en que se inició el algoritmo de secuencia de comandos.

La tarea que el origen de la tarea de red coloca en la cola de tareas una vez que el algoritmo de recuperación se ha completado debe ejecutar los siguientes pasos:

Si el elemento no es ahora el primer elemento en la lista de secuencias de comandos que se ejecutará en orden tan pronto como sea posible a la que se agregó anteriormente, entonces marque el elemento como listo, pero cancele estos pasos sin ejecutar la secuencia de comandos todavía.

Ejecución: ejecute el bloque de secuencia de comandos correspondiente al primer elemento de secuencia de comandos en esta lista de secuencias de comandos que se ejecutarán en orden tan pronto como sea posible.

Elimine el primer elemento de esta lista de scripts que se ejecutarán en orden tan pronto como sea posible.

Si esta lista de scripts que se ejecutarán en orden tan pronto como sea posible todavía no está vacía y la primera entrada ya se ha marcado como lista, salte al paso etiquetado ejecución.

Si el elemento tiene un atributo src El elemento debe agregarse al conjunto de scripts que se ejecutarán tan pronto como sea posible del Documento del elemento de script en el momento en que se inició el algoritmo de script.

La tarea que el origen de la tarea de red coloca en la cola de tareas una vez que el algoritmo de recuperación ha finalizado debe ejecutar el bloque de secuencias de comandos y luego eliminar el elemento del conjunto de secuencias de comandos que se ejecutarán tan pronto como sea posible.

De lo contrario, el agente de usuario debe ejecutar inmediatamente el bloque de script, incluso si ya se están ejecutando otros scripts.