JS之脚本延迟
自从开了博客,我就一下班回来匆匆吃完饭门一关等一开电脑一打开匆匆的研究东西,以至于朋友们都怀疑我是不是都得了自闭症

其实因为我有恐惧心理怕自己的技术哪天跟不上社会了,说到技术我觉得技术不求越新越好,但求越稳越好,就目前而言,前段框架五花八门,八面玲珑,一一都会
别吹牛了,在我看来找到自己的框架吃透它。不吹牛了,回归正题。
============================================================================================我们今天看下JS的脚本延迟
首先先看下浏览器是如何处理脚本的
1.浏览器一边下载HTML网页,一边开始解析
2.解析过程中,发现<script>标签
3.暂停解析,网页渲染的控制权转交给JavaScript引擎
4.如果<script>标签引用了外部脚本,就下载该脚本,否则就直接执行
5.执行完毕,控制权交还渲染引擎,恢复往下解析HTML网页
如果外部脚本加载时间很长(比如一直无法完成下载),就会造成网页长时间失去响应,浏览器就会呈现“假死”状态,这被称为“阻塞效应”。
为了避免这种情况,较好的做法是将<script>标签都放在页面底部,而不是头部。
怎样才能阻止这种状态呢
一下属性来解决
1.anync:改属性表示立即下载脚本,但不应妨碍页面的其他操作,改脚本只对外部脚本有效,属于异步脚本处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="a.js" async> </script> <script src="b.js" async></script>
</head>
<body>
<div>
<p>
HELLO world
</p> </div>
</body>
</html>
async属性的作用是,使用另一个进程下载脚本,下载时不会阻塞渲染。
浏览器如何渲染呢?
浏览器开始解析HTML网页 解析过程中,发现带有async属性的script标签 浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本 脚本下载完成,浏览器暂停解析HTML网页,开始执行下载的脚本 脚本执行完毕,浏览器恢复解析HTML网页
注意:async属性可以保证脚本下载的同时,浏览器继续渲染。需要注意的是,一旦采用这个属性,就无法保证脚本的执行顺序。哪个脚本先下载结束,就先执行那个脚本。
2..defer
defer也属于脚本延迟,其区别在于浏览器遇到该属性是不立即执行脚本而是等到加载到</html>在执行脚本,这样大大减少了浏览器假死的状态
步骤
浏览器开始解析HTML网页 解析过程中,发现带有defer属性的script标签 浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本 浏览器完成解析HTML网页,此时再执行下载的脚本
<script src="a.js" defer></script>
<script src="b.js" defer></script>
相比之下async的级别 >defer
==========================================================================================================================================
defer属性知多少
目前所有浏览器都支持defer属性,但是Chrome和Firefox中只有在加载外部脚本时defer才会生效,行内脚本使用defer是没有作用的。而IE中不论什么情况,defer都有效。
defer的作用就是阻止脚本在下载完成后立刻执行,它会让脚本延迟到所有脚本加载执行完成后,在DOMContentLoaded之前执行,通俗的说就是顺序加载延迟执行。虽然都是在DOMContentLoaded之前执行,但是在不同浏览器之间,执行的各种脚本执行的顺序还是不一样的。看下面这个例子:
<html>
<meta charset="utf-8">
<head>
<script type="text/javascript">
var result = "" ;
var head = document.getElementsByTagName("head")[0] ;
//DOMContentLoaded
if(window.addEventListener){
document.addEventListener("DOMContentLoaded",function(){
result += "DOMContentLoaded\n" ;
}) ;
}else{
document.attachEvent("onDOMContentLoaded",function(){
result += "DOMContentLoaded\n" ;
}) ;
}
window.onload = function(){
result += "window loaded\n";
//console.log("window loaded") ;
} ;
</script>
<!--头部行内延迟脚本-->
<script type="text/javascript" defer = "defer">
result += "Head Inline Script defer\n" ;
</script>
<!--头部行内脚本-->
<script type="text/javascript">
result += "Head Inline Script\n" ;
</script>
<!--头部外部延迟脚本 External Head Script defer-->
<script type="text/javascript" src = "external_head_defer.js" defer="defer"></script>
<!--头部行内脚本 External Head Script-->
<script type="text/javascript" src = "external_head.js"></script>
</head>
<body>
<button>SHOW</button>
<!--Body行内延迟脚本-->
<script type="text/javascript" defer = "defer">
result += "Body Inline Script defer\n" ;
</script>
<!--Body行内脚本-->
<script type="text/javascript">
result += "Body Inline Script\n" ;
</script>
<!--Body外部延迟脚本 External Body Script defer-->
<script type="text/javascript" defer = "defer" src = "external_body_defer.js"></script>
<!--Body外部脚本 External Body Script-->
<script type="text/javascript" src = "external_body.js"></script>
<script type="text/javascript">
document.getElementsByTagName("button")[0].onclick = function(){console.log(result);} ;
</script>
</body>
</html>

从上面可以看出几个问题:
首先,IE9以下不支持DOMContentLoaded(后面会说明这个情况)
其次,验证了上面说的Chrome和Firefox行内脚本不支持defer属性
最后,defer确实达到了延迟执行的目的,没有阻塞后面脚本的加载和执行。但是耗时的操作还是会阻塞DOMContentLoaded事件,而大多数情况下大家都会把页面初始化的脚本附加在DOMContentLoaded事件上,所以defer方法还是不能很好解决这个问题
END
虽然通过脚本后置和异步加载可以降低脚本加载对页面的影响,但是就算是实现了异步加载,但是由于浏览器的脚本解析的单线程的,所以脚本执行的时候仍然会阻塞整个页面(当然除了使用Web Worker),这时候用户是无法完成正常交互的,所以要想真正彻底的优化页面加载,还需要从代码的优化开始。
JS之脚本延迟的更多相关文章
- [No00007A]没有文件扩展".js"的脚本引擎 解决办法
在命令行运行JScript脚本时,遇到如下的错误提示: “输入错误: 没有文件扩展“.js”的脚本引擎.” 这样的错误,原因是因为JS扩展名的文件被其他软件关联了,需要取消关联. 如系统中安装了ULT ...
- cocos2dx的build_win32.dat出现问题以及install-template-msvc.dat出现.js没有脚本引擎
关于cocos2dx-2.x.x版本当中出现build_win32.bat执行失败 (针对VS2013)应当在VS的安装路径查找msbuild的文件夹,再其中查找msbuild.exe文件找到四个东西 ...
- JS的脚本语言
js的脚本语言全程javascript在网页里面使用的脚本语言:分类:1.嵌入网页里面2.在外部脚本标签可以写在网页的任何地方,但一般都写在网页的底部:<script type="te ...
- js中的延迟执行和定时执行
在js中,延迟执行函数有两种,setTimeout和setInterval,用法如下: function testFunction(){Console.log('hovertree.com');} s ...
- 没有文件扩展".js"的脚本引擎 解决办法
在命令行运行JScript脚本时,遇到如下的错误提示: “输入错误: 没有文件扩展“.js”的脚本引擎.” 这样的错误,原因是因为JS扩展名的文件被其他软件关联了,需要取消关联. 如系统中安装了ULT ...
- 没有文件扩展“.js”的脚本引擎问题解决
安装MinGW的时候提示没有文件扩展".js"的脚本引擎. 原因:系统安装Dreamwear.UltraEdit.EditPlus后修改了.js文件的默认打开方式.当想直接执行js ...
- node.js 设置脚本命令
yargs模块 https://www.npmjs.com/package/yargs https://github.com/yargs/yargs/blob/HEAD/docs/api.md con ...
- 没有文件扩展js的脚本引擎
没有文件扩展js的脚本引擎 没有文件扩展js的脚本引擎怎么解决_百度经验 https://jingyan.baidu.com/article/ff42efa93a7ad9c19e2202f0.html
- 用chrome的snippets片段功能创建页面js外挂程序,从控制台创建js小脚本
用chrome的snippets片段功能创建页面js外挂程序,从控制台创建js小脚本 Chrome的snippets是小脚本,还可以创作并在Chrome DevTools的来源面板中执行.可以访问和从 ...
随机推荐
- angular中封装fancyBox(图片预览)
首先在官网下载最新版的fancyBox(一定要去最新网站,以前依赖的jquery版本偏低),附上链接:http://fancyapps.com/fancybox/3/ 然后在项目中引用jquery,然 ...
- mysql简单主从复制(二)
mysql的简单主从复制 主从复制打开后,各自开启的线程: master端 mysql> show processlist\G; *************************** 1. r ...
- 使用jmeter进行批量数据创建
背景: 测试环境需要创建大量的测试数据,进行功能和性能的测试 测试数据创建接口是HTTP请求方式 测试数据要求不同类型的数据,要有字段进行关联,且单据的编号在DB中唯一不可重复,此外测试数据的时间类参 ...
- 打造基于Clang LibTooling的iOS自动打点系统CLAS(三)
1. 源码变换 第一章我们提到过,CLAS的本质是对源码做一次非常简单的变换(有些文章里称作变形),即Source-Source-Transformation,将打点代码精确地插入到目标函数的首部,保 ...
- 分享一个 jmeter ant的build.xml
<?xml version="1.0" encoding="UTF-8"?> <project name="ant-jmeter-t ...
- JavaScript实现隔行换颜色
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- Oracle实现分页查询的SQL语法汇总
1.无ORDER BY排序的写法.(效率最高) 经过测试,此方法成本最低,只嵌套一层,速度最快!即使查询的数据量再大,也几乎不受影响,速度依然! sql语句如下: ) TABLE_ALIAS ; 2. ...
- 1000以内完全数(完美数)获取实现---基于python
"""题目: 如果一个数恰好等于它的因子之和,则称该数为"完全数" .各个小于它的约数(真约数,列出某数的约数,去掉该数本身,剩下的就是它的真约数)的 ...
- 遇到的一些Jquery函数
jQuery.extend() jQuery.merge():函数用于合并两个数组内容到第一个数组. <script> $(function () { ,,], [,,] ...
- LINUX下C语言编程调用函数、链接头文件以及库文件
LINUX下C语言编程经常需要链接其他函数,而其他函数一般都放在另外.c文件中,或者打包放在一个库文件里面,我需要在main函数中调用这些函数,主要有如下几种方法: 1.当需要调用函数的个数比较少时, ...