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

May 16, 2016 pm 03:20 PM

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> 
Copier après la connexion

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>
Copier après la connexion
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:IE<=9的defer特性bug

从2.3节中的demo可以看出,defer后的脚本还是能够保持执行顺序的,也就是按照添加的顺序依次执行。而在IE<=9中,这个问题存在一个bug:假如我们向文档中增加了多个defer的脚本,而且之前的脚本中有appendChild,innerHTML,insertBefore,replaceChild等修改了DOM的接口调用,那么后面的脚本可能会先于该脚本执行。可以参考github的issue:https://github.com/h5bp/lazyweb-requests/issues/42

我们通过DEMO验证一下,首先修改1.js的代码为(这段代码只为模拟,事实上这段代码存在极大的性能问题):

document.body.innerHTML = "

我是后来加入的
";
document.body.innerHTML += "
我是后来加入的
";
document.body.innerHTML += "
我是后来加入的
";
document.body.innerHTML += "
我是后来加入的
";
document.body.innerHTML += "
我是后来加入的
";
document.body.innerHTML += "
我是后来加入的
";
document.body.innerHTML += "
我是后来加入的
";
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>
Copier après la connexion

正常情况下,浏览器中弹出框的顺序肯定是:我是第1个脚本-》我是第2个脚本,然而在IE<=9中,执行结果却为:我是第2个脚本-》我是第1个脚本,验证了这个bug。

2.5 defer总结

在总结之前,首先要说一个注意点:正如标准中提到的,defer的脚本中不应该出现document.write的操作,浏览器会直接忽略这些操作。

总的来看,defer的作用一定程度上与将脚本放置在页面底部有一定的相似,但由于IE<=9中的bug,如果页面中出现多个defer时,脚本的执行顺序可能会被打乱从而导致代码依赖可能会出错,因此实际项目中很少会使用defer特性,而将脚本代码放置在页面底部可以替代defer所提供的功能。

3 async特性

3.1 关于async脚本的执行时机

async特性是HTML5中引入的特性,使用方式为:async="async",我们首先看一下标准中对于async特性的相关描述:

async:If the async attribute is present, then the script will be executed asynchronously, as soon as it is available.

需要指出,这里的异步,指的其实是异步加载而不是异步执行,也就是说,浏览器遇到一个async的script标签时,会异步的去加载(个人认为这个过程主要是下载的过程),一旦加载完毕就会执行代码,而执行的过程肯定还是同步的,也就是阻塞的。我们可以通过下图来综合理解defer和async:


这样来看的话,async脚本的执行时机是无法确定的,因为脚本何时加载完毕也是不确定的。我们通过下面的demo来感受一下:

async1.js

alert("我是异步的脚本");

HTML代码:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>async attribute test</title>
<script src="/delayfile.php&#63;url=http://localhost/js/load/async1.js&delay=2" async="async" type="text/javascript"></script>
<script>
alert("我是同步的脚本");
</script>
</head>
<body>
</body>
</html> 
Copier après la connexion

여기서는 "브라우저 환경의 JavaScript 스크립트 로딩 및 실행 분석: 코드 실행 순서"에서 지연 파일 스크립트를 빌려 비동기를 지원하는 브라우저에서 이 스크립트의 팝업 상자 순서가 일반적입니다. : 나는 동기 스크립트입니다 -> 나는 비동기 스크립트입니다.

3.2 브라우저 비동기 지원

비동기 기능에 대한 브라우저 지원을 살펴보겠습니다.

보시다시피 IE10만 비동기 기능을 지원하고, Opera Mini는 비동기 기능을 지원하지 않으며, 비동기는 내부 스크립트를 지원하지 않습니다.

3.3 비동기 요약

async는 비동기식 스크립트를 의미합니다. 즉, 스크립트가 비동기적으로 로드되는 과정은 블로킹을 일으키지 않지만, 비동기 스크립트의 실행 시기도 불확실하고, 실행 순서도 불확실하므로 비동기를 사용하는 스크립트는 반드시 코드(예: 타사 통계 코드 또는 광고 코드)에 의존하지 않는 스크립트. 그렇지 않으면 실행 오류가 발생합니다.

지연과 비동기 사이의 4가지 우선순위 문제

이 표준은 다음과 같이 규정하고 있습니다.

[1]

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

Repo: Comment relancer ses coéquipiers
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
4 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Remplacer les caractères de chaîne en javascript Remplacer les caractères de chaîne en javascript Mar 11, 2025 am 12:07 AM

Explication détaillée de la méthode de remplacement de la chaîne JavaScript et de la FAQ Cet article explorera deux façons de remplacer les caractères de chaîne dans JavaScript: le code JavaScript interne et le HTML interne pour les pages Web. Remplacer la chaîne dans le code JavaScript Le moyen le plus direct consiste à utiliser la méthode Remplace (): str = str.replace ("trouver", "remplacer"); Cette méthode remplace uniquement la première correspondance. Pour remplacer toutes les correspondances, utilisez une expression régulière et ajoutez le drapeau global G: str = str.replace (/ fi

Tutoriel de configuration de l'API de recherche Google personnalisé Tutoriel de configuration de l'API de recherche Google personnalisé Mar 04, 2025 am 01:06 AM

Ce tutoriel vous montre comment intégrer une API de recherche Google personnalisée dans votre blog ou site Web, offrant une expérience de recherche plus raffinée que les fonctions de recherche de thème WordPress standard. C'est étonnamment facile! Vous pourrez restreindre les recherches à Y

8 Superbes plugins de mise en page JQuery Page 8 Superbes plugins de mise en page JQuery Page Mar 06, 2025 am 12:48 AM

Tirez parti de jQuery pour les dispositions de page Web sans effort: 8 plugins essentiels JQuery simplifie considérablement la mise en page de la page Web. Cet article met en évidence huit puissants plugins jQuery qui rationalisent le processus, particulièrement utile pour la création de sites Web manuels

Créez vos propres applications Web Ajax Créez vos propres applications Web Ajax Mar 09, 2025 am 12:11 AM

Vous voici donc, prêt à tout savoir sur cette chose appelée Ajax. Mais qu'est-ce que c'est exactement? Le terme Ajax fait référence à un regroupement lâche de technologies utilisées pour créer un contenu Web interactif dynamique. Le terme Ajax, inventé à l'origine par Jesse J

Qu'est-ce que & # x27; ceci & # x27; en javascript? Qu'est-ce que & # x27; ceci & # x27; en javascript? Mar 04, 2025 am 01:15 AM

Points de base Ceci dans JavaScript fait généralement référence à un objet qui "possède" la méthode, mais cela dépend de la façon dont la fonction est appelée. Lorsqu'il n'y a pas d'objet actuel, cela fait référence à l'objet global. Dans un navigateur Web, il est représenté par Window. Lorsque vous appelez une fonction, cela maintient l'objet global; mais lors de l'appel d'un constructeur d'objets ou de l'une de ses méthodes, cela fait référence à une instance de l'objet. Vous pouvez modifier le contexte de ceci en utilisant des méthodes telles que Call (), Appliquer () et Bind (). Ces méthodes appellent la fonction en utilisant la valeur et les paramètres donnés. JavaScript est un excellent langage de programmation. Il y a quelques années, cette phrase était

10 feuilles de triche mobiles pour le développement mobile 10 feuilles de triche mobiles pour le développement mobile Mar 05, 2025 am 12:43 AM

Ce message compile des feuilles de triche utiles, des guides de référence, des recettes rapides et des extraits de code pour le développement d'Android, BlackBerry et Iphone. Aucun développeur ne devrait être sans eux! Guide de référence sur les gestes touchés (PDF) Une ressource précieuse pour Desig

Améliorez vos connaissances jQuery avec le spectateur source Améliorez vos connaissances jQuery avec le spectateur source Mar 05, 2025 am 12:54 AM

JQuery est un excellent cadre JavaScript. Cependant, comme pour n'importe quelle bibliothèque, il est parfois nécessaire de passer sous le capot pour découvrir ce qui se passe. C'est peut-être parce que vous tracez un bug ou que vous êtes simplement curieux de savoir comment jQuery réalise une interface utilisateur particulière

Comment créer et publier mes propres bibliothèques JavaScript? Comment créer et publier mes propres bibliothèques JavaScript? Mar 18, 2025 pm 03:12 PM

L'article discute de la création, de la publication et du maintien des bibliothèques JavaScript, en se concentrant sur la planification, le développement, les tests, la documentation et les stratégies de promotion.

See all articles