异步脚本加载

阻塞性脚本

JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析、渲染以及其他资源的下载都要停下来等待脚本执行完毕

浏览器是按照从上到下的顺序解析页面,因此正常情况下,JavaScript脚本的执行顺序也是从上到下的,即页面上先出现的代码或先被引入的代码总是被先执行,即使是允许并行下载JavaScript文件时也是如此。注意我们这里标红了”正常情况下”,原因是什么呢?我们知道,在HTML中加入JavaScript代码有多种方式,概括如下(不考虑require.js或sea.js等模块加载器):

(1)正常引入:即在页面中通过<script>标签引入脚本代码或者引入外部脚本
(2)通过document.write方法向页面写入<script>标签或代码
(3)通过动态脚本技术,即利用DOM接口创建<script>元素,并设置元素的src,然后再将元素添加进DOM中。
(4)通过Ajax获取脚本内容,然后再创建<script>元素,并设置元素的text,再将元素添加进DOM中。
(5)直接把JavaScript代码写在元素的事件处理程序中或直接作为URL的主体

具体参考 http://www.jb51.net/article/77920.htm

脚本延迟运行

一般在JS页面延迟执行一些方法。可以使用以下的方法:


Window.setTimeout jQuery.delay jQuery.queue和jQuery.dequeue
<script src="deferdemo.js" defer></script>

加上 defer 等于在页面完全在入后再执行,相当于 window.onload ,但应用上比 window.onload 更灵活!

<script type="text/javascript" src="demo_async.js" async="async"></script>

使用async属性,浏览器会下载js文件,同时继续对后面的内容进行渲染

通常如果js不需要改变DOM结构时可以使用async进行异步加载(比如一些统计代码可以异步加载,因为此代码与页面执行逻辑无关,不会改变DOM结构)

SeaJS与RequireJS

网上写amd和cmd的文章很多,当然也有很多都是误人子弟的片面的看法,所以还是推荐自己看官方文档多加尝试去理解。

“RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范”。

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

amd 规划 https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96%87%E7%89%88)

cmd 规范 https://github.com/seajs/seajs/issues/242

区别:

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)

  2. CMD 推崇依赖就近,AMD 推崇依赖前置。

ECMAScript6 Moudle

历史上,JavaScript一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如Ruby的require、Python的import,甚至就连CSS都有@import
到了ES6,实现了模块化的功能,功能上基本可以取代 cmd和amd的规范,

模块的功能主要由两个命令构成,export和import,export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

export的写法,

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958; export {firstName, lastName, year};

上面代码在export命令后面,使用大括号指定所要输出的一组变量。

import写法:

// main.js

import {firstName, lastName, year} from './profile';

function setName(element) {
element.textContent = firstName + ' ' + lastName;
}

ES6模块加载的实质

ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。CommonJS模块输出的是被输出值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值

ES6模块的运行机制与CommonJS不一样,它遇到模块加载命令import时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,换句话说,ES6的输入有点像Unix系统的”符号连接“,原始值变了,import输入的值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

// mod.js
function C() {
this.sum = 0;
this.add = function () {
this.sum = 1;
};
this.show = function () {
console.log(this.sum);
}
} export let c = new C();

上面的脚本mod.js,输出的是一个C的实例。不同的脚本加载这个模块,得到的都是同一个实例

// x.js
import {c} from './mod';
c.add(); // y.js
import {c} from './mod';
c.show(); // main.js
import './x';
import './y';

现在执行main.js,输出的是1。
证明加载的是同一个实例
参考 http://es6.ruanyifeng.com/#docs/module

深入理解JS异步编程五(脚本异步加载)的更多相关文章

  1. C# 异步编程2 EAP 异步程序开发

    在前面一篇博文记录了C# APM异步编程的知识,今天再来分享一下EAP(基于事件的异步编程模式)异步编程的知识.后面会继续奉上TPL任务并行库的知识,喜欢的朋友请持续关注哦. EAP异步编程算是C#对 ...

  2. php为什么需要异步编程?php异步编程的详解(附示例)

    本篇文章给大家带来的内容是关于php为什么需要异步编程?php异步编程的详解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 我对 php 异步的知识还比较混乱,写这篇是为了 ...

  3. vue3 + vite实现异步组件和路由懒加载

    在 Vue2 中,异步组件和路由懒加载处理使用 import 就可以很轻松实现.但是在Vue 3.x 中异步组件的使用与 Vue 2.x 完全不同了.本文就详细讲讲vue3中异步组件和路由懒加载的实现 ...

  4. 【原创】从零开始搭建Electron+Vue+Webpack项目框架(五)预加载和Electron自动更新

    导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更 ...

  5. HTML文档、javascript脚本的加载与解析

    1.onload事件 1.1 onload事件分类 a.文档加载完成事件(包括脚本.图片等资源都加载完),绑定方法:<body onload="doSomething()"& ...

  6. js实现类型jq的dom加载完成

    有时候我们只想在 dom 加载完成后运行 js ,而不是等所有图片加载完成.所以不需要 onload , onload 会加载图片等其他媒体.很消耗时间. 原:http://blog.csdn.net ...

  7. angularjs ocLazyLoad分步加载js文件,angularjs ocLazyLoad按需加载js

    用angular有一段时间了,平日里只顾着写代码,没有注意到性能优化的问题,而今有时间,于是捋了捋,讲学习过程记录于此: 问题描述:由于采用angular做了网页的单页面应用,需要一次性在主布局中将所 ...

  8. win7,vs2010,asp.net项目中修改外部js文件,在调试时加载的还是旧文件

    win7,vs2010,asp.net项目中修改外部js文件,在调试时加载的还是旧文件 我杀过 w3wp.exe和asp.net_state的进程,重启 iis admin的服务,都还是不行. 只是把 ...

  9. Unity基础-脚本的加载与编译顺序

    脚本的加载与编译顺序 C#是以Assembly(汇编集)为一个基本单元组织代码的,dll就是一个assembly,dll之间有加载以来顺序 Assets/*.dll Stamdard Assets/* ...

  10. FreeSql (二十五)延时加载

    FreeSql 支持导航属性延时加载,即当我们需要用到的时候才进行加载(读取),支持1对1.多对1.1对多.多对多关系的导航属性. 当我们希望浏览某条订单信息的时候,才显示其对应的订单详细记录时,我们 ...

随机推荐

  1. IE9 使用document.getElementsByName("abc") 不能获取到名称相同SPAN元素

    <div name="abc"></div> <input name="abc" type="text" /& ...

  2. .NET中的动态编译

    代码的动态编译并执行是一个.NET平台提供给我们的很强大的工具用以灵活扩展(当然是面对内部开发人员)复杂而无法估算的逻辑,并通过一些额外的代码来扩展我们已有 的应用程序.这在很大程度上给我们提供了另外 ...

  3. AES--高级数据加密标准

    AES--高级数据加密标准 对称密码体制的发展趋势将以分组密码为重点.分组密码算法通常由密钥扩展算法和加密(解密)算法两部分组成.密钥扩展算法将b字节用户主密钥扩展成r个子密钥.加密算法由一个密码学上 ...

  4. 用openvswitch配置跨节点的docker网络环境

    在一篇随笔中,我们已经尝试了在不依赖工具的情况下设置docker的ip,连我都想吐槽,MD单机都这么麻烦,在多机的环境中岂不是要了我的小命! 本文就是为了多机环境中各个节点的容器通信而做的,网络拓朴如 ...

  5. [转]-CSS 元素垂直居中的6种方法

    原文地址:http://blog.zhourunsheng.com/2012/03/css-%E5%85%83%E7%B4%A0%E5%9E%82%E7%9B%B4%E5%B1%85%E4%B8%AD ...

  6. Nexus3.0.0+Maven的使用(三)

    这章主要讲怎么和Maven做集成,集成的方式主要分以下种情况:代理中央仓库.Snapshot包的管理.Release包的管理.第三方Jar上传到Nexus上 1  代理中央仓库 只要在PMO文件中配置 ...

  7. [ActionScript 3.0] 将组件 SWC 文件导入 Flash

    在向其它开发人员分发组件时,您可以包含以下说明,以便他们能够立即安装和使用组件.  导入 SWC 文件: 将 SWC 文件复制到 Configuration/Components 目录中. 重新启动 ...

  8. [AS3.0] HTMLLoader与js交互

    HtmlLoader 的属性window是加载到 HTML 控件中的内容的全局 JavaScript 对象,通过这个对象能够方便的和页面js通讯. AS代码: import flash.html.HT ...

  9. C++ 几种构造函数的区分和调用

    class A { public: A(); //默认构造 A( A& a ); //copy构造 const A& operator=( const A& a ); //赋值 ...

  10. [转]SQL Server 连接串关键字别名

    转自:http://stackoverflow.com/questions/3077412/what-is-the-difference-between-trusted-connection-and- ...