JS的异步加载

异步加载

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

从这张图里我们可以看到如下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里面的全部函数的方式,则是一种多余的带宽浪费。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cesium是一个用于创建地球和其他天体的3D地理信息系统(GIS)可视化的开源JavaScript库。在Cesium异步加载是一种常见的技术,用于在加载大型数据集或复杂场景时提高性能和用户体验。 异步加载是指在加载资源时,不阻塞主线程,而是通过并行加载渲染来提高效率。在Cesium异步加载主要应用于以下几个方面: 1. 模型加载:Cesium支持加载各种3D模型格式,如glTF、COLLADA等。当加载大型模型时,可以使用异步加载来避免页面卡顿或加载时间过长的问题。 2. 影像加载:Cesium可以加载各种影像数据,如卫星影像、地形数据等。由于影像数据通常较大,使用异步加载可以提高加载速度和用户体验。 3. 矢量数据加载:Cesium支持加载各种矢量数据格式,如GeoJSON、KML等。当加载大量矢量数据时,可以使用异步加载来提高性能和交互响应速度。 在Cesium异步加载通常通过使用Promise对象来实现。Promise是一种用于处理异步操作的对象,它可以表示一个异步操作的最终完成或失败,并返回相应的结果。 下面是一个示例代码,演示了如何使用异步加载加载一个3D模型: ```javascript // 创建一个Promise对象 var promise = Cesium.Model.fromGltf({ url: 'path/to/model.gltf', basePath: 'path/to/assets' }); // 当模型加载完成后,执行回调函数 promise.then(function(model) { // 将模型添加到场景 viewer.scene.primitives.add(model); }).otherwise(function(error) { // 加载失败时的处理逻辑 console.log('An error occurred: ' + error); }); ``` 在上面的代码,`Cesium.Model.fromGltf`方法返回一个Promise对象,表示模型的异步加载过程。通过调用`then`方法和`otherwise`方法,可以分别指定加载成功和失败时的回调函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值