2017-08-29 2 views
1

Webpack prend en charge la syntaxe import() conforme à ECMAScript proposal pour les importations dynamiques. Cette syntaxe utilise des promesses de chargement asynchrone de modules.Comment détecter quand un module dynamique et toutes ses dépendances ont été chargés?

Le problème est que la promesse est résolue dès que le module spécifique est chargé, sans attendre le chargement des dépendances du module (ce qui peut être n'importe quel type d'actif, y compris JS & CSS).

code Exemple:

import('./myModule.js').then(myModule => { 
    myModule.sayHello(); // This will be called before someCSS.css has been loaded 
}); 

myModule.js

import './someCSS.css'; // <-- I need to know when this is loaded (there can be more than one asset) 

export default class myModule { 
    sayHello() { 
     alert('Hello!'); 
    } 
} 

Comment puis-je détecter le module, et tous les actifs liés, ont été chargés? Quelque chose comme un événement onload pour les actifs asynchrones?

Répondre

0

La méthode renvoie Promise, qui vous permet de déterminer si un script a été chargé ou une erreur est survenue lors du chargement (par exemple):

// utils.js 
function insertJs({src, isModule, async, defer}) { 
    const script = document.createElement('script'); 

    if(isModule){ 
     script.type = 'module'; 
    } else{ 
     script.type = 'application/javascript'; 
    } 
    if(async){ 
     script.setAttribute('async', ''); 
    } 
    if(defer){ 
     script.setAttribute('defer', ''); 
    } 

    document.head.appendChild(script); 

    return new Promise((success, error) => { 
     script.onload = success; 
     script.onerror = error; 
     script.src = src;// start loading the script 
    }); 
} 

export {insertJs}; 

//An example of its use: 

import {insertJs} from './utils.js' 

// The inserted node will be: 
// <script type="module" src="js/module-to-be-inserted.js"></script> 
const src = './module-to-be-inserted.js'; 

insertJs({ 
    src, 
    isModule: true, 
    async: true 
}) 
    .then(
     () => { 
      alert(`Script "${src}" is successfully executed`); 
     }, 
     (err) => { 
      alert(`An error occured during the script "${src}" loading: ${err}`); 
     } 
    ); 
// module-to-be-inserted.js 
alert('I\'m executed'); 
+0

La promesse est résolue lorsque le script est chargé, indépendamment de ses dépendances. Voir ma mise à jour pour plus d'informations. –

+0

@YoavKadosh Vous avez un problème de conception alors. Ce sont les dépendances du module enfant. Le module parent ne doit pas compter sur eux. S'il a besoin de ces dépendances, le module parent doit également les importer. – estus

+0

Ils ne sont pas nécessaires dans le module parent. J'ai besoin de savoir quand ils sont disponibles afin de cacher le fileur. –

0

Il est possible d'utiliser document.styleSheets pour vérifier lorsque toutes les feuilles de style ont été chargées. Un objet CSSStyleSheet contiendra une propriété cssRules une seule fois la feuille de style a été chargé, de sorte que vous pouvez créer une promesse qui vérifie que contre:

export function awaitStylesheets() { 
    let interval; 
    return new Promise(resolve => { 
     interval = setInterval(() => { 
      for (let i = 0; i < document.styleSheets.length; i++) { 
       // A stylesheet is loaded when its object has a 'cssRules' property 
       if (typeof document.styleSheets[i].cssRules === 'undefined') { 
        return; 
       } 
      } 

      // Only reached when all stylesheets have been loaded 
      clearInterval(interval); 
      resolve(); 
     }, 10); 
    }); 
}