Le script peut-il être reconnu pour détecter la fin du chargement du script dynamique?

J'utilise le chargement de script dynamique pour réduire la durée de la charge de page initiale. Pour s'assurer que les fonctions et les objets définis par un script sont accessibles, je dois vous assurer que le script a été entièrement chargé.

J'ai développé ma propre bibliothèque Javascript à cette fin, et j'ai donc fait beaucoup de recherches sur le sujet, en étudiant comment cela se fait dans différentes bibliothèques. Lors d'une discussion sur cette question, Kyle Simpson, l'auteur de LABjs , a déclaré:

LABjs (et beaucoup d'autres chargeurs) définissent à la fois "onload" et "onreadystatechange" sur tous les éléments du script, sachant que certains navigateurs vont enrayer un, et certains détruiront l'autre …

Vous pouvez en trouver un exemple dans la version actuelle de jQuery à partir de cette écriture, 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 ); } }; 

C'est l'état de l'art, mais lors de l'analyse d'un comportement étrange dans Opera 9.64, je suis arrivé à la conclusion que, en utilisant cette technique, le rappel de recharge a été lancé trop tôt.

Je publierai mes propres résultats en réponse à cette question et j'aimerais recueillir d'autres preuves et commentaires de la part de la communauté.

Dans Opera, la propriété script.readyState ne peut pas faire confiance. Par exemple, le readyState "chargé" peut être déclenché avant que le script ne s'exécute dans Opera 9.64.

J'ai effectué le même test dans Opera 9.64 et Opera 10, avec des résultats différents.

Dans Opera 9.64, le gestionnaire de change onreadystate est déclenché deux fois, une fois avant et une fois après l'exécution du script. La propriété readyState est "chargée" dans les deux cas, ce qui signifie que cette valeur ne peut pas faire confiance pour détecter la fin du chargement du script:

 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 

Dans Opera 10, le gestionnaire de change onreadystate reçoit encore deux fois la valeur "chargé", mais les deux fois après le script:

 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 

Ces différents comportements indiquent que onreadystatechange n'est pas un moyen fiable de détecter la fin d'un chargement de script dans Opera. Comme Opera prend également en charge l'auditeur onload, cet autre mécanisme devrait être utilisé à la place.

Sur la base des résultats de ces tests, onreadystatechange ne doit être utilisé que pour détecter la fin du chargement de script dans Internet Explorer et ne doit pas être configuré dans d'autres navigateurs.

Dans Firefox, Safari et Chrome, l'onreadystatechange handler nevers s'appelle.

J'ai créé un cas de test court, créant un script dynamique avec seulement le set de gestionnaire de change onreadystate:

 <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> 

J'ai effectué le test sur un fichier local dans Firefox 2, Firefox 3, Firefox 3.5, Safari 3, Safari 4 et Chrome 3, et obtenu des résultats similaires (ici les journaux enregistrés dans 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 

Le numéro de référence n'est jamais appelé. Dans ces navigateurs, seul l'auditeur onload est utile pour détecter la fin d'un chargement de script, mais la version en ligne n'est pas nécessaire.

Dans Internet Explorer, le gestionnaire de modification de l'état de l'enregistrement se déclenche comme prévu, après la fin du script.

J'ai effectué le même test dans Internet Explorer 6, Internet Explorer 7 et Internet Explorer 8, avec des résultats similaires dans ces trois navigateurs (ici les journaux enregistrés dans 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 

Ici, avec un test utilisant un fichier local, readyState est toujours "complet", et il était toujours le même après plusieurs actualisations.

Cependant, comme l'a noté dans cette publication par Nicholas C. Zakas , vous pouvez également observer "chargé" et "compléter", ou simplement "chargé", dans des circonstances différentes.

J'ai trouvé que Internet Explorer (test dans 9) N'AVEZ PAS TOUJOURS votre script prêt lorsque readyState === 'loaded'. J'ai réussi à utiliser ce gestionnaire d'événements (en 9 évidemment) en cours de désactivation . Je me retirais les cheveux avant.

Des résultats similaires dans Chrome.

Ne prend pas en compte …

Il suffit de charger et de surcharger.