异步加载

先看一张整体的异步加载对渲染的阻塞情况图,图片如下:

从这张图里我们可以看到如下4点:

  • 默认情况HTML解析,然后加载JS,此时HTML解析中断,然后执行JS,最后JS执行完成恢复HTML解析
  • defer情况下HTML和JS并驾齐驱,最后才执行JS
  • async情况则HTML和JS并驾齐驱,JS的执行可能在HTML解析之前就已经完成了
  • 最后module情况和defer的情况类似,只不过会在提取的过程中加载多个JS文件罢了

然后我们再来看一下这几种加载JS的情形与DOM事件、onload事件的关系:

从上面的图片我们可以看到如下几点:

  • async 会在加载完JS后立即执行,最迟也会在load事件前执行完。
  • defer会在HTML解析完成后执行,最迟也会在DOMContentLoaded事件前执行完。

从上面我们可以看出,如果你的脚本依赖于DOM构建完成是否完成,则可以使用defer;如果无需DOM的构建,那就可以放心的使用async了。

defer

defer属性仅适用于外部脚本,也就是仅当存在src属性时才会生效;如果一个script标签上面即存在defer属性,也存在async属性,那么浏览器会如何解析这种情况呢?我们通过一段代码验证结果,详情点击这里

也就是说defer的优先级没有async高,我们看一下规范是怎么处理这种情况的。

The defer attribute may be specified even if the async attribute is specified, to cause legacy Web browsers that only support defer (and not async) to fall back to the defer behavior instead of the blocking behavior that is the default.

规范只是说明了在不支持async的情况下浏览器将会回退支持defer,但并没有明确指明两种都支持的这种情况,也就是说这一种情况浏览器自行处理,经过测试,各个浏览器表现行为:

  • Chrome浏览器表现为解析为async特性
  • Safari浏览器表现为async特性
  • Opera浏览器表现为async特性
  • Firefox浏览器表现为async特性

IE暂时没有安装,看来各大浏览器表现一致,总之async的优先级是最高的。

defer兼容性

下面来看看defer的兼容性,移动端一片大绿,可以放心使用,IE10以上可以放心使用,IE6-9有一点小问题就是不会按照script标签的执行顺序进行执行,对于不依赖前后脚本库的可以不用担心,但是如果依赖库的就不行了,比如你的项目依赖jQuery,后面紧接着使用jQuery的方法可能就会出现问题。

asyc

和defer一样,也仅仅适用于外部脚本,也就是仅当存在src属性时才会生效。

async兼容性

async的兼容性在移动端也是一片大绿,IE仅支持IE10+。

module

在现代浏览器中,我们可以声明acript标签type=’module’属性从而拥抱es6的模块导入导出语法,就像这样:

1 <script type="module">
2 import { Max } from "./math.js";
3 console.log(Max(1, 2, 7, 2, 0)); //7
4 </script>

看起来是不是令人很激动,似乎对于开发者十分友好,但是这里也有几个与传统脚本不一样的地方:

  • module默认使用了”use strict”模式,这也意味着不能使用诸如arguments.callee这一类的语法。
  • 模块只会加载一次,无论前后你写了多少次
  • 不支持<!–const a = 1–>注释。
  • module有自己的词法作用域,比如定义一个 var a = 1,并不会创建一个全局变量,因此你并不能通过window.a 访问到它的值

模块的导入方式目前仅支持以下几种模式:

1 支持
2 import {math} from './math.mjs';
3 import {math} from '../math.mjs';
4 import {math} from '/modules/math.mjs';
5 import {math} from 'https://simple.example/modules/math.mjs';
6 //不支持
7 import {math} from 'jquery';

当然,浏览器厂商也在考虑支持 import {math} from ‘jquery’ 这种格式,不过,还是需要一段很长的路要走。

module的默认情况就是defer的,因此不必再module上面又添加一个defer熟悉,并且本身就不支持这种写法,但是支持async属性,其加载渲染方式和async差不多,这里不再赘述。

module兼容性

在移动端的兼容性还算可以,但是IE貌似都败下阵来,只要edge16+以上还算支持,对于不支持module的浏览器可以使用nomodule属性作为版本回退的方案解决。

最后来说一下module的使用建议,大型项目(100模块以上)不建议直接使用模块语法,应该使用打包工具诸如Webpack,Rollup,、或 Parcel,因为静态导入或导出语法是静态可分析的,通过捆绑工具可以去掉多余的模块,我们考虑下面这一种场景:
1 import { Modal } from './util.js';
2 Modal({
3 title: 'hello'
4 })
如果我们通过打包工具打包这一份代码,最终生成的JS文件将会只包含Modal这一个函数,倘若我们没有使用打包工具,浏览器将会下载整个util这一个JS文件,并通过进一步分析了解了使用了Modal这一个函数,这对于没有用到util里面的全部函数的方式,则是一种多余的带宽浪费。
 

JS的异步加载的更多相关文章

  1. js的异步加载你真的懂吗

    面试高频之js的异步加载 讲这个问题之前, 我们从另一个面试高频问题来切入, 我们的web页面从开始解析到页面渲染完成都经历了什么 ?  1  ,  创建document对象, 开始解析页面,    ...

  2. Vue中结合Flask与Node.JS的异步加载功能实现文章的分页效果

    你好!欢迎阅读我的博文,你可以跳转到我的个人博客网站,会有更好的排版效果和功能. 此外,本篇博文为本人Pushy原创,如需转载请注明出处:http://blog.pushy.site/posts/15 ...

  3. js滚动异步加载数据的思路

    <body> <div style="width:200px; height:1000px; border:1px solid red;" id="to ...

  4. JS异步加载的三种方案

    js加载的缺点:加载工具方法没必要阻塞文档,个别js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作. 有些工具方法需要按需加载,用到再加载,不用不加载. 一.def ...

  5. 异步加载的JS如何在chrome浏览器断点调试?

    我们常常利用chrome强大的控制台Sources下面进行代码断点调试,但是通过$.getScript等异步加载JS的方式在Sources里面就是找不到,那如何进行debug断点调试呢? 方案一: 在 ...

  6. 不得不说的JavaScript异步加载

    同步加载的问题 默认的js是同步加载的,这里的“加载”可以理解成是解析.执行,而不是“下载”,在最新版本的浏览器中,浏览器对于代码请求的资源都是瀑布式的加载,而不是阻塞式的,但是js的执行总是阻塞的. ...

  7. javascript 同步加载与异步加载

    HTML 4.01 的script属性 charset: 可选.指定src引入代码的字符集,大多数浏览器忽略该值. defer: boolean, 可选.延迟脚本执行,相当于将script标签放入页面 ...

  8. Highcharts 异步加载数据曲线图表

    导入 data.js 文件 异步加载数据需要引入以下js 文件: <script src="http://code.highcharts.com/modules/data.js&quo ...

  9. Javascript 文件的同步加载与异步加载

    HTML 4.01 的script属性 charset: 可选.指定src引入代码的字符集,大多数浏览器忽略该值.defer: boolean, 可选.延迟脚本执行,相当于将script标签放入页面b ...

  10. Highcharts 基本曲线图;Highcharts 带有数据标签曲线图表;Highcharts 异步加载数据曲线图表

    Highcharts 基本曲线图 实例 文件名:highcharts_line_basic.htm <html> <head> <meta charset="U ...

随机推荐

  1. React组件封装:文字、表情评论框

    1.需求描述 根据项目需求,采用Antd组件库需要封装一个评论框,具有以下功能: 支持文字输入 支持常用表情包选择 支持发布评论 支持自定义表情包 2.封装代码 ./InputComment.tsx ...

  2. Scala mutable.Map可变的Map

    1 package chapter07 2 3 import scala.collection.mutable 4 5 object Test09_MutableMap { 6 def main(ar ...

  3. #分治 or 线段树+单调栈#CF526F Pudding Monsters

    题目 给定一个 \(n \times n\) 的棋盘,其中有 \(n\) 个棋子,每行每列恰好有一个棋子. 求有多少个 \(k \times k\) 的子棋盘中恰好有 \(k\) 个棋子. 分析 先将 ...

  4. #对勾函数#洛谷 5695 [NOI2001]反正切函数的应用

    题目 问给定的每一个\(a\),是否存在正整数\(b,c\), 使得在满足$$\arctan(\frac{1}{a})=\arctan(\frac{1}{b})+\arctan(\frac{1}{c} ...

  5. #根号分治,背包#51nod 1597 有限背包计数问题 LOJ 6089 小Y的背包计数问题

    题目 有一个大小为\(n\)的背包,有\(n\)种物品, 第\(i\)种物品的大小为\(i\),且有\(i\)个, 求装满这个背包的方案数 \(n\leq 10^5\) 分析 直接多重背包会有问题,考 ...

  6. 使用OHOS SDK构建opus

    参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone --depth=1 https://github.com/xiph/opus 进入 ...

  7. SQL LIKE 运算符:用法、示例和通配符解释

    SQL中的LIKE运算符用于在WHERE子句中搜索列中的指定模式.通常与LIKE运算符一起使用的有两个通配符: 百分号 % 代表零个.一个或多个字符. 下划线 _ 代表一个单个字符. 以下是LIKE运 ...

  8. 自动编号工具类:NumAutoUtils详解

    在软件开发中,经常需要生成唯一的编号,例如订单号.发票号.实验编号等.为了简化这一过程,本文将介绍一个Java工具类NumAutoUtils,它可以帮助我们生成带有前缀和日期的自动编号. 概述 Num ...

  9. 应用缺少POI数据,如何开发地点深度信息?

    用户在App里搜索某个地点时,并不满足单一的地点信息,希望得到更多可以帮助其做决策的深度信息.例如有打车出行需求的用户,在打车App里搜索地点时可以显示周边的地点,精确到某个路口,让用户可以自由选择合 ...

  10. MogDB/openGauss 坏块测试-对启动的影响-测试笔记1

    MogDB/openGauss 坏块测试-对启动的影响-测试笔记 1 在 UPDATE 操作提交后,脏块落盘前 kill 掉 mogdb 数据库,然后对 UPDATE 修改的坏进行以下破坏操作,仍然能 ...