详解JS前端异步文件加载篇之Async与Defer区别

目录

同步、异步及推迟的概念

async和defer解决文件加载阻塞问题


          在了解async和defer的区别之前,我们需要先了解同步、异步和推迟的概念。

同步、异步及推迟的概念

        假如现在有一条非常狭隘的胡同,里面有两个人挨着走,那么现在请问后面的人能够跑快点走到前面那个人前面吗?肯定是不行的,因为路太窄了过不去。如果后面那个人比较急,而前面那个人又有腿伤跑不快呢,这就好比代码的阻塞情况。这两个人都被堵在了胡同里,那么这个胡同就像JS的执行引擎是主线程的一样,所有代码被限制在了一个主线程上,而这个正是 同步 的概念。

        同步的阻塞是一种非常糟糕的情况,所以这时候我们可以再添加一条胡同,那么这两个人就可以各走各自的路,不需要在乎前面是否有人堵着自己过不去了,后面那个人像走到前面也就非常容易了,这个就是 异步 的概念。

        虽然现在分出了两个胡同,但这两个人用的是一个出口,那么这两个人就会出现谁先出出口的问题。这个时候我们需要为异步增加一个条件,那就是后面的人必须等到前面的人出去后自己才能出去,这个便是 推迟 的概念。

async和defer解决文件加载阻塞问题

         异步的英语是async,推迟的英语是defer,同步的就不说了哈。但同步是Javascript中一个非常重要的概念。当浏览器加载HTML时一旦遇到<script>标签, 就会停下来先把<script>标签里的内容执行掉,如果<script>标签中有外部文件,那就必须等待下载和执行的步骤,这样浏览器才会继续向下加载,如果这个外部文件刚好在一个网络情况比较差的服务器上,这样整个网页的加载都会收到很大的影响,这就是同步带来的代码阻塞弊端。

async和defer都可以解决这个问题,先看下面这段代码:

<!-- HTML代码 -->
<body>
	<script src="./index.js"></script>
	<div>Hello world!</div>
</body>
// JS代码
console.log(document.querySelector("div"));

可以看到,在HTML的body标签中引入了JS文件,打印div元素。此时<script>标签是没有加 async 和 defer属性的,那么这个时候就会出现上面讲到的同步问题,不仅会阻塞了代码执行,还会出现JS脚本文件访问不到下面HTML代码的而出现打印结果为 null 的情况。但如果我们在<script>标签中加入了 async 或 defer 属性后,就不会出现这种代码阻塞的问题了,比如下面这种:

<body>
	<script src="./index.js" async></script>
	<div>Hello world!</div>
</body>
<!-- 或者 -->
<body>
	<script src="./index.js" defer></script>
	<div>Hello world!</div>
</body>

async:浏览器在加载页面的时候,如果遇到了async属性,浏览器就会立即进行下载,与此同时还会继续加载页面,这样就解决了阻塞的问题,虽然没有阻塞的情况,但是async下请求的脚本具体什么时候执行就说不定了,有时页面还没加载完就执行了,也有可能页面加载后才执行,因为这种不确定性,如果脚本是需要修改DOM的,那么就有可能会出错,因此,async比较适合一些第三方脚本。

defer: 浏览器加载时如果遇到defer属性,浏览器就会立即进行下载,与此同时还会继续加载页面,但相较于async的区别就来了,因为不管脚本是否下载完了, defer都会等待浏览器解析完了html之后再去执行脚本,因此defer比较适合与DOM操作有关联的脚本。

        不管是async还是defer,两者都 只适用于外部脚本,且还需要注意兼容性问题(如果浏览器不能识别这两个属性,那还是把script标签内容放在页面底部比较好)

        以上就是我对于async和defer的理解了,希望能够有所帮助!

猜你喜欢

转载自blog.csdn.net/weixin_60678263/article/details/127990681