En mi sitio web uso módulos de javascript, que según MDN están diferidos por defecto . Tengo un javascript adicional que solo puede ejecutarse de manera segura una vez que estos módulos se hayan cargado y ejecutado. MDN indica aquí que se garantiza que la ejecución diferida del script se haya producido en el momento en que se dispare el evento DOMContentLoaded . Además, se sugiere aquí que también puede tener en cuenta el caso en el que este evento ya se ha disparado así:
function doSomething() { console.info('DOM loaded'); } if (document.readyState === 'loading') { // Loading hasn't finished yet document.addEventListener('DOMContentLoaded', doSomething); } else { // `DOMContentLoaded` has already fired doSomething(); } El bloque de arriba parece ser lo que estoy buscando. Pero la documentación en otras partes de MDN me deja sin saber si esto es realmente correcto. Por ejemplo, ¿por qué la verificación de readystate anterior busca loading en lugar de loading O interactive ? La documentación en readystate dice que la loading es seguida por interactive , y que en el estado interactive "los subrecursos como secuencias de comandos , imágenes, hojas de estilo y marcos aún se están cargando ".
Así que me parece que hay una inconsistencia aquí. La verificación de readystate sugerida no es suficiente para garantizar que DOMContentLoaded se haya activado, o DOMContentLoaded no es suficiente para garantizar que se hayan completado los scripts diferidos.
Cuando readyState es al menos interactive , eso significa que el documento se ha analizado por completo y que todos los elementos en el HTML de origen ahora existen en el DOM.
Por lo general, las personas que implementan esta solución lo hacen porque intentan adjuntar oyentes a los elementos y necesitan esperar a que todos los elementos existan en el DOM, por lo que todo lo que deben hacer es verificar document.readyState === 'loading' .
Si también desea esperar a que se ejecuten los scripts de <script type="module"> , ese es un problema diferente, con una solución diferente.
La mejor manera, por mucho, sería tener un único punto de entrada para su aplicación en un módulo, de modo que no tenga que preocuparse por el orden de carga en absoluto, simplemente funcionará.
Si realmente tiene que determinar cuándo se ejecutaron todos los scripts de módulos desde un script que no es de módulo (que no recomendaría), tendría que iterarlos y escuchar sus eventos de load .
// run this at the end of the body - // once all script tags exist, but before they've run Promise.all( [...document.querySelectorAll('script[type="module"]')] .map(script => new Promise( resolve => script.addEventListener('load', resolve) )) ) .then(() => { // all module scripts are loaded })Pero eso es bastante complicado y probablemente no sea un buen enfoque.
Si escucha el evento de load para la ventana, también estará esperando que se carguen todos los demás recursos (imágenes y hojas de estilo y demás), lo cual no es deseable.
import "other-module"; // module is guaranteed to be loaded hereAl importar el módulo, se puede garantizar que se cargue antes de que se ejecute el módulo en el que se está importando.