search
HomeWeb Front-endJS TutorialAnalysis of JavaScript script loading and execution in browser environment: defer and async characteristics_javascript skills

The defer and async features are believed to be two features that many JavaScript developers are "familiar but not familiar with". From a literal point of view, the functions of the two are easy to understand. They are "delay script" and "asynchronous script" respectively. effect. However, taking defer as an example, developers may not necessarily be familiar with some details, such as: when will a script with the defer feature be delayed to be executed; whether both internal scripts and external scripts can support defer; scripts after defer In addition to delayed execution, what are the special features, etc. This article combines some existing articles and the description of the two features in MDN documents to conduct a more comprehensive study and summary of defer and async, hoping to help developers better master these two features.

1 Introduction

In "Analysis of JavaScript Script Loading and Execution in the Browser Environment: Code Execution Sequence" we mentioned that the execution of JavaScript code will block the parsing and rendering of the page and the downloading of other resources. Of course, due to JavaScript is a single-threaded language, which means that under normal circumstances, the JavaScript code in a page can only be executed in order from top to bottom. Of course, as in " Analysis of JavaScript Script Loading and Execution in the Browser Environment As we analyzed in "Execution Sequence ", in some cases, such as when entering a script through document.write or introducing a script through dynamic script technology, the execution order of JavaScript code does not necessarily follow the strict order from top to bottom. defer and async are also what we call "abnormal situations".

We often say that the execution of JavaScript is blocking. In actual development, the blocking that we are usually most concerned about and the blocking that affects the user experience the most should be the following aspects:

[1] Blocking of page parsing and rendering

[2] The page initialization script we wrote (generally the script bound to listen to the DOMContentLoaded event). This part of the script is the script we want to execute first, because we will write the code most relevant to user interaction here. )

[3] Blocking of downloading external resources on the page (such as pictures)

If we have a time-consuming script operation, and this script blocks the three places we mentioned above, then the performance or user experience of this web page will be very poor.

The original intention of the two features of defer and async is also to solve or alleviate the impact of blocking on the page experience. Let’s analyze these two features below. We mainly understand these two from the following aspects. Features:

[1]When is the execution time of delayed or asynchronous scripts? What about page blocking?

[2] Are both internal and external scripts capable of delay or asynchronous implementation?

[3]How well does the browser support these two features? Are there any related bugs?

[4] Is there anything else that needs to be paid attention to when using scripts that use these two features?

2 defer feature

2.1 About the execution timing of defer script

The defer feature is an extended feature defined in the HTML4 specification. Initially, it was only supported by IE4 and Firefox3.5. Later, browsers such as Chrome also added support for it, using defer="defer". defer means delay, which means it will delay the execution of the script. Under normal circumstances, the script we introduce will be downloaded and executed immediately. However, with the defer feature, the script will not be executed immediately after downloading, but will be executed after the page is parsed. Let’s take a look at the HTML4 standard’s explanation of defer:

defer: When set, this boolean attribute provides a hint to the user agent that the script is not going to generate any document content (e.g., no "document.write" in javascript) and thus, the user agent can continue parsing and rendering.

In other words, if defer is set, it tells the user agent that this script will not produce any document content, so that the user agent can continue to parse and render. Let’s take another look at the key description of defer in MDN:

defer: If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing.

Through the definition in the standard, we can make it clear that the defer script will not block the parsing of the page, but will wait until the page parsing is completed before executing it. However, the time-consuming defer may still block the download of external resources, then Will it block the DOMContentLoaded event? In fact, the defer script is still executed before the DOMContentLoaded event, so it will still block the script in DOMContentLoaded. We can use the following figure to help understand the execution timing of the defer script:


According to the definition in the standard, internal scripts do not support defer, but browsers IE9 and below provide defer support for internal scripts.

2.2 defer browser support

Let’s take a look at browser support for the defer feature:


There is a bug in IE9 and below browsers, which will be explained in detail in the DEMO later.

2.3 DEMO: Function verification of defer feature

We imitate the method used by Olivier Rochard in "the script defer attribute" to verify the function of the defer attribute:

First we prepared 6 external scripts:

1.js:

test = "I am head external script n";

2.js

test = "I am a body external script n";

3.js

test = "I am the bottom external script n";

defer1.js

test = "I am head external delay script n";

defer2.js

test = "I am body external delay script n";

defer3.js

test = "I am the bottom external delay script n";

The code in HTML is:

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

In the code, in order to facilitate the implementation of the DOMContentLoaded event, we introduced jQuery (later articles will introduce how to implement compatible DOMContentLoaded yourself). Then, we introduced delay scripts in the head, inside the body and outside the body of the script. and normal scripts, and records the execution status of each piece of code through a global string. Let’s take a look at the execution results in each browser:

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>
I am head external script I am head internal script I am a body external script I am the bottom external script I am head external delay script I am head delay internal script I am a body external delay script I am the bottom external delay script I am the script in DOMContentLoaded I am the script in window.onload
I am head external script I am head internal script I am a body external script I am the bottom external script I am head external delay script I am head delay internal script I am a body external delay script I am the bottom external delay script I am the script in DOMContentLoaded I am the script in window.onload I am head external script I am head delayed internal script I am head internal script I am a body external script I am the bottom external script I am head external delay script I am a body external delay script I am the bottom external delay script I am the script in DOMContentLoaded I am the script in window.onload I am head external script I am head delayed internal script I am head internal script I am a body external script I am the bottom external script I am head external delay script I am a body external delay script I am the bottom external delay script I am the script in DOMContentLoaded I am the script in window.onload

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

2.4 DEMO:IE

从2.3节中的demo可以看出,defer后的脚本还是能够保持执行顺序的,也就是按照添加的顺序依次执行。而在IEhttps://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>

正常情况下,浏览器中弹出框的顺序肯定是:我是第1个脚本-》我是第2个脚本,然而在IE

2.5 defer总结

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

总的来看,defer的作用一定程度上与将脚本放置在页面底部有一定的相似,但由于IE

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> 

Here we borrow the delayfile script in "Analysis of JavaScript Script Loading and Execution in Browser Environment: Code Execution Sequence" to provide a delay. In browsers that support async, the order of the pop-up boxes of this script is generally: I am a synchronous script -> I am an asynchronous script.

3.2 Browser support for async

Let’s take a look at browser support for async features:

As you can see, only IE10 supports the async feature. Opera mini does not support the async feature. In addition, async does not support internal scripts.

3.3 async summary

async refers to asynchronous scripts, that is, scripts are loaded asynchronously. The loading process will not cause blocking, but the execution timing of async scripts is uncertain, and the order of execution is also uncertain, so scripts using async should be Scripts that do not rely on any code (such as third-party statistics code or advertising code), otherwise it will cause execution errors.

4 Priority issues between defer and async

This is easier to understand. The standard stipulates:

[1] If the <script> element defines both defer and async attributes, it will be processed as async (note: browsers that do not support async will directly ignore the async attribute) <br /> </script>

[2] If the <script> element only defines defer, it will be processed as a delayed script <br /> </script>

[3] If the <script> element does not define defer or async, it will be processed as normal, that is: the script will be loaded and executed immediately <br /> </script>

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Python vs. JavaScript: The Learning Curve and Ease of UsePython vs. JavaScript: The Learning Curve and Ease of UseApr 16, 2025 am 12:12 AM

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python vs. JavaScript: Community, Libraries, and ResourcesPython vs. JavaScript: Community, Libraries, and ResourcesApr 15, 2025 am 12:16 AM

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

From C/C   to JavaScript: How It All WorksFrom C/C to JavaScript: How It All WorksApr 14, 2025 am 12:05 AM

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

JavaScript Engines: Comparing ImplementationsJavaScript Engines: Comparing ImplementationsApr 13, 2025 am 12:05 AM

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

Beyond the Browser: JavaScript in the Real WorldBeyond the Browser: JavaScript in the Real WorldApr 12, 2025 am 12:06 AM

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.

Building a Multi-Tenant SaaS Application with Next.js (Backend Integration)Building a Multi-Tenant SaaS Application with Next.js (Backend Integration)Apr 11, 2025 am 08:23 AM

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

How to Build a Multi-Tenant SaaS Application with Next.js (Frontend Integration)How to Build a Multi-Tenant SaaS Application with Next.js (Frontend Integration)Apr 11, 2025 am 08:22 AM

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

JavaScript: Exploring the Versatility of a Web LanguageJavaScript: Exploring the Versatility of a Web LanguageApr 11, 2025 am 12:01 AM

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Atom editor mac version download

Atom editor mac version download

The most popular open source editor