Si no carga dinámicamente los scripts o los marca como defer
o async
, los scripts se cargan en el orden que se encuentran en la página. No importa si se trata de 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 los scripts externos se mantienen hasta que todos los scripts externos que vinieron antes que ellos se hayan cargado y ejecutado.
Las secuencias de comandos asíncronas (independientemente de cómo se especifiquen como asíncronas) 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 varias cosas asíncronas. Si se necesitara un orden predecible, entonces tendría que codificarse al registrarse para recibir notificaciones de carga de los scripts asíncronos y secuenciar manualmente las llamadas de JavaScript cuando se cargan las cosas apropiadas.
Cuando una etiqueta de script se inserta dinámicamente, 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 secuencia de comandos agregada dinámicamente a asíncrono a menos que la etiqueta de secuencia de comandos se haya establecido de otra manera.
Una etiqueta de script con async
puede ejecutarse tan pronto como se cargue. De hecho, el navegador puede pausar el analizador de cualquier otra cosa que esté haciendo y ejecutar ese script. Por lo tanto, realmente puede ejecutarse en casi cualquier momento. Si el script se almacenó en caché, podría ejecutarse casi de inmediato. Si el script tarda un tiempo en cargarse, podría ejecutarse después de que se complete el analizador. Una cosa para recordar async
es que puede ejecutarse en cualquier momento y que el tiempo no es predecible.
Una etiqueta de secuencia de comandos defer
espera hasta que se complete el analizador completo y luego ejecuta todas las secuencias de comandos marcadas 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 que finalice el analizador de documentos, pero se ejecutarán en el orden en que se encontraron preservando sus dependencias. Pienso que defer
los scripts se colocan en una cola que se procesará después de que se complete el analizador. Técnicamente, el navegador puede estar descargando 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 analice y ejecute los scripts en línea que no están marcados defer
o async
.
Aquí hay una cita de ese artículo:
los scripts insertados con script se ejecutan de forma asincrónica en IE y WebKit, pero sincrónicamente en Opera y Firefox anterior a 4.0.
La parte relevante de la especificación HTML5 (para navegadores compatibles más nuevos) está aquí . Hay mucho escrito allí sobre el comportamiento asíncrono. Obviamente, esta especificación no se aplica a los navegadores más antiguos (o navegadores mal conformes) 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 describe 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 sintáctico", 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 finalizado el análisis asociado con el Documento del analizador que creó el elemento.
La tarea que la fuente de la tarea de red coloca en la cola de tareas una vez que el algoritmo de recuperación se ha completado 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 el script de bloqueo de análisis pendiente del documento del analizador que lo creó. (Solo puede haber una secuencia de comandos por documento a la vez).
La tarea que la fuente de la tarea de red coloca en la cola de tareas una vez que el algoritmo de recuperación se ha completado 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 sintáctico", y el Documento del analizador HTML o analizador XML que creó el elemento de secuencia de comandos tiene una hoja de estilo que bloquea las secuencias de comandos. El elemento es el script de bloqueo de análisis pendiente del documento del analizador que creó el elemento. (Solo puede haber una secuencia de comandos 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 establecido el indicador "force-async". El elemento debe agregarse al final de la lista de scripts que se ejecutarán en orden lo antes posible. con el documento del elemento de secuencia de comandos en el momento en que se inició la preparación de un algoritmo de secuencia de comandos.
La tarea que la fuente de la tarea de red coloca en la cola de tareas una vez que se ha completado el algoritmo de recuperación debe ejecutar los siguientes pasos:
Si el elemento no es ahora el primer elemento en la lista de scripts que se ejecutará en orden tan pronto como sea posible al que se agregó anteriormente, marque el elemento como listo pero cancele estos pasos sin ejecutar el script 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á en orden lo antes posible.
Elimine el primer elemento de esta lista de scripts que se ejecutarán en orden lo antes posible.
Si esta lista de secuencias de comandos que se ejecutará en orden lo antes posible aún no está vacía y la primera entrada ya se ha marcado como lista, luego vuelva al paso etiquetado como ejecución.
Si el elemento tiene un atributo src El elemento debe agregarse al conjunto de scripts que se ejecutarán lo antes posible del Documento del elemento de script en el momento en que se inicia el algoritmo de preparación de un script.
La tarea que la fuente de la tarea de red coloca en la cola de tareas una vez que el algoritmo de recuperación se ha completado debe ejecutar el bloque de secuencia de comandos y luego eliminar el elemento del conjunto de secuencias de comandos que se ejecutará lo antes posible.
De lo contrario, el agente de usuario debe ejecutar inmediatamente el bloque de script, incluso si ya se están ejecutando otros scripts.
¿Qué pasa con los scripts del módulo Javascript type="module"
?
Javascript ahora tiene soporte para cargar módulos con una sintaxis como esta:
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
O, con src
atributo:
<script type="module" src="http://somedomain.com/somescript.mjs">
</script>
Todos los scripts con type="module"
reciben automáticamente el defer
atributo. Esto los descarga en paralelo (si no en línea) con otra carga de la página y luego los ejecuta en orden, pero después de que se realiza el analizador.
Los scripts del módulo también pueden recibir el async
atributo que ejecutará los scripts del módulo en línea tan pronto como sea posible, sin esperar hasta que se complete el analizador y sin esperar a ejecutar el async
script en un orden particular en relación con otros scripts.
Hay un gráfico de línea de tiempo bastante útil que muestra la búsqueda y ejecución de diferentes combinaciones de scripts, incluidos los scripts de módulo aquí en este artículo: Carga del módulo Javascript .