Maison >interface Web >js tutoriel >Analyse du chargement et de l'exécution de scripts JavaScript dans un environnement de navigateur : caractéristiques différées et asynchrones_compétences Javascript

Analyse du chargement et de l'exécution de scripts JavaScript dans un environnement de navigateur : caractéristiques différées et asynchrones_compétences Javascript

WBOY
WBOYoriginal
2016-05-16 15:20:021647parcourir

Les fonctionnalités de report et async sont considérées comme deux fonctionnalités que de nombreux développeurs JavaScript sont "familières mais pas familières". D'un point de vue littéral, les fonctions des deux sont faciles à comprendre. et "script asynchrone" respectivement. Cependant, en prenant le report comme exemple, les développeurs ne sont pas nécessairement familiers avec certains détails, tels que : quand un script avec la fonctionnalité defer sera-t-il retardé pour être exécuté ; si les scripts internes et les scripts externes peuvent prendre en charge les scripts defer après le report ; en plus de l'exécution différée, quelles sont les particularités, etc. Cet article combine certains articles existants et la description des deux fonctionnalités dans les documents MDN pour mener une étude plus complète et un résumé du report et de l'async, dans l'espoir d'aider les développeurs à mieux maîtriser ces deux fonctionnalités.

1 Introduction

Dans "Analyse du chargement et de l'exécution du script JavaScript dans l'environnement du navigateur : séquence d'exécution du code" nous avons mentionné que l'exécution du code JavaScript bloquera l'analyse et le rendu de la page ainsi que le téléchargement d'autres ressources. . Bien sûr, étant donné que JavaScript est un langage monothread, ce qui signifie que dans des circonstances normales, le code JavaScript d'une page ne peut être exécuté que dans l'ordre de haut en bas. Bien sûr, comme dans " Analyse de JavaScript. Chargement et exécution du script dans l'environnement du navigateur Comme nous l'avons analysé dans « Séquence d'exécution », dans certains cas, par exemple lors de la saisie d'un script via document.write ou de l'introduction d'un script via la technologie de script dynamique, l'ordre d'exécution du code JavaScript ne ne suivent pas nécessairement l'ordre strict de haut en bas. le report et l'async sont aussi ce que nous appelons des « situations anormales ».

Nous disons souvent que l'exécution de JavaScript est bloquante. Dans le développement réel, le blocage qui nous préoccupe généralement le plus et celui qui affecte le plus l'expérience utilisateur devrait être les aspects suivants :

[1] Blocage de l'analyse et du rendu des pages

[2] Le script d'initialisation de la page que nous avons écrit (généralement le script destiné à écouter l'événement DOMContentLoaded). Cette partie du script est le script que nous souhaitons exécuter en premier, car nous écrirons le code le plus pertinent pour l'interaction de l'utilisateur. ici. )

[3] Blocage du téléchargement de ressources externes sur la page (telles que des images)

Si nous avons une opération de script qui prend du temps et que ce script bloque les trois endroits que nous avons mentionnés ci-dessus, alors les performances ou l'expérience utilisateur de cette page Web seront très mauvaises.

L'intention initiale des deux fonctionnalités defer et async est également de résoudre ou d'atténuer l'impact du blocage sur l'expérience de la page. Analysons ces deux fonctionnalités ci-dessous. Nous comprenons ces deux principalement sous les aspects suivants :

[1]Quelle est l'heure d'exécution des scripts retardés ou asynchrones ? Qu'en est-il du blocage de pages ?


[2] Les scripts internes et externes sont-ils capables d'une mise en œuvre retardée ou asynchrone ?


[3] Dans quelle mesure les navigateurs prennent-ils en charge ces deux fonctionnalités ? Y a-t-il des bugs associés ?


[4] Y a-t-il autre chose auquel il faut prêter attention lors de l'utilisation de scripts qui utilisent ces deux fonctionnalités ?


Fonction de 2 reports

2.1 À propos du timing d'exécution du script de report

La fonctionnalité de report est une fonctionnalité étendue définie dans la spécification HTML4. Initialement, elle n'était prise en charge que par IE4 et Firefox 3.5. Plus tard, des navigateurs tels que Chrome l'ont également ajouté, en utilisant defer="defer". defer signifie retard, ce qui signifie que cela retardera l'exécution du script. Dans des circonstances normales, le script que nous introduisons sera téléchargé et exécuté immédiatement. Cependant, avec la fonction de report, le script ne sera pas exécuté immédiatement après le téléchargement, mais sera exécuté après l'analyse de la page. Jetons un coup d'œil à l'explication du report dans la norme HTML4 :


defer : lorsqu'il est défini, cet attribut booléen indique à l'agent utilisateur que le script ne générera aucun contenu de document (par exemple, pas de "document.write" en javascript) et que l'agent utilisateur peut donc continuer l'analyse. et le rendu.


En d'autres termes, si defer est défini, il indique à l'agent utilisateur que ce script ne produira aucun contenu de document, afin que l'agent utilisateur puisse continuer à analyser et à restituer. Jetons un autre coup d'œil à la description clé du report dans MDN :


defer : Si l'attribut async n'est pas présent mais que l'attribut defer est présent, alors le script est exécuté lorsque la page a terminé l'analyse

.

Grâce à la définition de la norme, nous pouvons indiquer clairement que le script defer ne bloquera pas l'analyse de la page, mais attendra que l'analyse de la page soit terminée avant de l'exécuter. Cependant, le defer, qui prend beaucoup de temps, peut toujours. bloquer le téléchargement de ressources externes, puis bloquera-t-il l'événement DOMContentLoaded ? En fait, le script defer est toujours exécuté avant l'événement DOMContentLoaded, il bloquera donc toujours le script dans DOMContentLoaded. Nous pouvons utiliser la figure suivante pour aider à comprendre le timing d'exécution du script defer :



Selon la définition de la norme, les scripts internes ne prennent pas en charge le report, mais les navigateurs IE9 et inférieurs fournissent une prise en charge différée pour les scripts internes.


2.2 différer la prise en charge du navigateur

Jetons un coup d'œil à la prise en charge par les navigateurs de la fonctionnalité de report :


Il y a un bug dans les navigateurs IE9 et inférieurs, qui sera expliqué en détail plus tard dans la DÉMO.

2.3 DÉMO : Vérification du fonctionnement de la fonction de report

Nous imitons la méthode utilisée par Olivier Rochard dans "le script defer attribut" pour vérifier la fonction de l'attribut defer :

Nous avons d'abord préparé 6 scripts externes :

1.js:

test = "Je suis responsable du script externe n"

2.js

test = "Je suis un corps externe script n"

3.js

test = "Je suis le script externe du bas n"

defer1.js

test = "Je suis responsable du script de delay externe n"
;

defer2.js

test = "Je suis un script de retard externe du corps n"
;

defer3.js

test = "Je suis le script de retard externe inférieur n"
;

Le code en HTML est :

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>defer attribute test</title>
<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
<script type="text/javascript">var test = "";</script>
<script src="defer1.js" type="text/javascript" defer="defer"></script>
<script src="1.js" type="text/javascript"></script>
<script defer="defer">
test += "我是head延迟内部脚本\n";
</script>
<script>
test += "我是head内部脚本\n";
</script>
</head>
<body>
<button id="test">点击一下</button>
<script src="defer2.js" type="text/javascript" defer="defer"></script>
<script src="2.js" type="text/javascript"></script>
</body>
<script src="defer3.js" type="text/javascript" defer="defer"></script>
<script src="3.js" type="text/javascript"></script>
<script>
$(function(){
test += "我是DOMContentLoaded里面的脚本
";
})
window.onload = function(){
test += "我是window.onload里面的脚本
";
var button = document.getElementById("test");
button.onclick = function(){
alert(test);
}
}
</script>
</html> 

Dans le code, afin de faciliter l'implémentation de l'événement DOMContentLoaded, nous avons introduit jQuery (des articles ultérieurs expliqueront comment implémenter vous-même un DOMContentLoaded compatible. Ensuite, nous avons introduit des scripts de retard dans la tête, à l'intérieur du corps et à l'extérieur du). corps du script et des scripts normaux, et enregistre l'état d'exécution de chaque morceau de code via une chaîne globale. Jetons un coup d'œil aux résultats d'exécution dans chaque navigateur :
.

IE7 IE9 IE10 CHROME firefox
IE7 IE9 IE10 CHROME firefox

我是head外部脚本
我是head内部脚本
我是body外部脚本
我是底部外部脚本
我是head外部延迟脚本
我是head延迟内部脚本
我是body外部延迟脚本
我是底部外部延迟脚本
我是DOMContentLoaded里面的脚本
我是window.onload里面的脚本

我是head外部脚本
我是head内部脚本
我是body外部脚本
我是底部外部脚本
我是head外部延迟脚本
我是head延迟内部脚本
我是body外部延迟脚本
我是底部外部延迟脚本
我是DOMContentLoaded里面的脚本
我是window.onload里面的脚本

我是head外部脚本
我是head延迟内部脚本
我是head内部脚本
我是body外部脚本
我是底部外部脚本
我是head外部延迟脚本
我是body外部延迟脚本
我是底部外部延迟脚本
我是DOMContentLoaded里面的脚本
我是window.onload里面的脚本

我是head外部脚本
我是head延迟内部脚本
我是head内部脚本
我是body外部脚本
我是底部外部脚本
我是head外部延迟脚本
我是body外部延迟脚本
我是底部外部延迟脚本
我是DOMContentLoaded里面的脚本
我是window.onload里面的脚本

<br />我是head外部脚本
<span style="color: rgb(255,0,0)">我是head延迟内部脚本</span>
我是head内部脚本
我是body外部脚本
我是底部外部脚本
我是head外部延迟脚本
我是body外部延迟脚本
我是底部外部延迟脚本
<span style="color: rgb(255,0,0)">我是DOMContentLoaded里面的脚本
我是window.onload里面的脚本</span>
Je suis responsable script externe Je suis responsable du script interne Je suis un script externe au corps Je suis le script externe du bas Je suis responsable du script de delay externe Je suis responsable du script interne du retard Je suis un script de retard externe au corps Je suis le script de delay externe du bas Je suis le script dans DOMContentLoaded Je suis le script dans window.onload
Je suis responsable script externe Je suis responsable du script interne Je suis un script externe au corps Je suis le script externe du bas Je suis responsable du script de delay externe Je suis responsable du script interne du retard Je suis un script de retard externe au corps Je suis le script de delay externe du bas Je suis le script dans DOMContentLoaded Je suis le script dans window.onload Je suis responsable script externe Je suis en tête du script interne retardé Je suis responsable du script interne Je suis un script externe au corps Je suis le script externe du bas Je suis responsable du script de delay externe Je suis un script de retard externe au corps Je suis le script de delay externe du bas Je suis le script dans DOMContentLoaded Je suis le script dans window.onload Je suis responsable script externe Je suis en tête du script interne retardé Je suis responsable du script interne Je suis un script externe au corps Je suis le script externe du bas Je suis responsable du script de delay externe Je suis un script de retard externe au corps Je suis le script de delay externe du bas Je suis le script dans DOMContentLoaded Je suis le script dans window.onload

从输出的结果中我们可以确定,只有IE9及以下浏览器支持内部延迟脚本,并且defer后的脚本都会在DOMContentLoaded事件之前触发,因此也是会堵塞DOMContentLoaded事件的。

2.4 DEMO:IE0f630a08ba48c70580451c5807d38ff4我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
alert("我是第1个脚本");

2.js

alert("我是第2个脚本");

修改HMTL中的代码为:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>defer bug in IE=9 test</title>
<script src="1.js" type="text/javascript" defer="defer"></script>
<script src="2.js" type="text/javascript" defer="defer"></script>
</head>
<body>
</body>
</html>

正常情况下,浏览器中弹出框的顺序肯定是:我是第1个脚本-》我是第2个脚本,然而在IE77f5db5c498cd8790c183e49397570fd 요소가 defer 및 async 속성을 모두 정의하는 경우 비동기로 처리됩니다(참고: 비동기를 지원하지 않는 브라우저는 비동기 속성을 직접 무시합니다)

[2] 3f1c4e4b6b16bbbd69b2ee476dc4f83a 요소가 defer만 정의하는 경우 지연된 스크립트로 처리됩니다.

[3] 3f1c4e4b6b16bbbd69b2ee476dc4f83a 요소가 defer 또는 async를 정의하지 않으면 정상적으로 처리됩니다. 즉, 스크립트가 즉시 로드되고 실행됩니다.

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn