第三十二课:JSDeferred的性能提速
大家如果看了前面两课,就知道Deferred的静态方法next(next_default)是用setTimeout实现的(有浏览器最小时钟间隔)。但是实现这种异步操作,可以有很多种方法。JSDeferred中,针对老版本IE,以及标准浏览器都专门使用了一些方法来实现异步操作,提高异步操作的性能提速。
首先,我们先来看下针对老版本IE的提速。
Deferred.next_faster_way_readystatechange =
(location.protocol == "http:") && IE && //这里的location是window对象下(document.location这样使用也行,)的一个属性对象,它有很多属性,比如:href,protocol等,href属性值是当前页面的URL地址(等于document.URL),protocol属性值是当前页面URL的协议,一般是"htttp:","https:"等。如果是http请求,并且是老版本IE浏览器,就继续
function(fun){ //大家都知道&&的操作吧,前面如果都返回真,那么就返回后面这个。这里前面两个操作如果都返回真,那么这个&&操作会返回function。
var d = new Deferred();
var t = new Date().getTime();
if( t - arguments.callee._prev_timeout_called < 150){ //这里先判断当前的时间与函数的_prev_timeout_called 属性值相减小于150毫秒就进入if语句。第一次执行时,函数的_prev_timeout_called 属性值是undefined,因此不会进入if语句(而使用原始的setTimeout方法)。第二次调用这个方法时,它会检查第二次调用这个方法与上一次调用这个方法的时间间隔,如果事件间隔小于150毫秒,就用速度更快的方法实现异步操作。如果超过了150毫秒,就用setTimeout方法实现。
var cancel = false;
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "data:text/javascript";
script.onreadystatechange = function(){ //加载一个不存在的资源,引发onerror,但是老版本IE不管是引发onerror还是onload都会引起onreadystatechange触发,因此就会执行这个函数。这里的异步操作时间非常短(在老版本IE下,这里的时间会短于setTimeout(function(){},0)的时间),但是足够让用户通过next实例方法绑定回调函数了。
if(!cancel){
d.canceller();
d.call();
}
};
d.canceller = function(){
if(!cancel){
cancel = true;
script.onreadystatechange = null;
document.body.removeChild(script);
}
};
document.body.appendChild(script); //因为这里需要把新建的script标签添加到页面中,所以我们的Deferred最好延迟到domReady或onload后执行
}
else{
arguments.callee._prev_timeout_called = t; //这里保存第一次执行此方法的时间,arguments.callee代表这个函数function(fun)。
var id = setTimeout(function(){
d.call();
}, 0 );
d.canceller = function(){
clearTimeout(id);
}
}
if(fun){
d.callback.ok = fun;
}
return d
};
这里我要说下,为什么要设置一个150毫秒的时间。大家都知道当我们在老版本IE下进行jsonp操作时,浏览器会进行请求,每新建一个script,并且设置它的src,并添加到页面上就会进行请求。如果不设置这个150毫秒的时间,那么如果每次异步操作都使用这种jsonp的方式,那么浏览器会同时进行N多个请求。而大家知道,IE6-7下,浏览器的并发请求是2-4个,IE8-9是6个。如果多余这个数量,那么请求就会被堵塞。导致使用这种方式的异步操作,时间花的更长,那这提速方法,就没有意义了。因此,我们在这里设置一个150毫秒的时间,在150毫秒内,它的jsonp的请求不可能会出现很多个。我们来举个例子:第一次异步操作,默认会使用setTimeout的方法,这时的时间是0(保存为_prev_timeout_called ),第二次异步操作,时间是40毫秒,小于150,所以使用jsonp方式,第三次异步操作,时间是80毫秒,小于150,使用jsonp方式,第四次异步操作,时间是120毫秒,小于150,使用jsonp方式。当第五次异步操作来临时,它的当前时间是160毫秒,这时160-_prev_timeout_called =160>150,使用setTimeout方式,并且保存_prev_timeout_called为160。因此,这里同时使用了三次jsonp方式,浏览器的并发请求是3个,没有超过浏览器的并发请求数,不会堵塞。
针对标准浏览器的加速如下:
Deferred.next_faster_way_image = !window.opera && document.addEventListener && //标准浏览器,并且不是opera浏览器,就继续。
function(fun){
var d = new Deferred();
var img = new Image();
var handler = function(){
d.canceller();
d.call();
};
img.addEventListener("load",handler,false); //加载一个不存在的图片,会触发error事件。之所有绑定了onload事件,以防图片存在。
img.addEventListener("error",handler,false);
d.canceller = function(){
img.removeEventListener("load",handler,false);
img.removeEventListener("error",handler,false);
};
img.src = "data:image/png," + Math.random(); //这里之所以加上随机数,是因为图片会缓存,以防图片存在的情况下被缓存了,这样就不会发请求,也就不会有异步效果了。
if(fun){
d.callback.ok = fun;
}
return d;
};
根据JSDeferred官方的数据,用上这两个后,比原来的setTimeout异步方式快了700%以上。
JSDeferred不单单是运行于网页上,它还能在浏览器的插件环境以及node.js上运行。node.js已经支持快的惊人的最新异步API:setImmediate方法了。
当然,这些提速的方式因为都属于异步操作,因此都会有延迟效果,最快的方式就是不使用异步操作,jQuery Deferred就是使用精妙数组结构实现的,下一课将详细讲解它。
加油!
第三十二课:JSDeferred的性能提速的更多相关文章
- NeHe OpenGL教程 第三十二课:拾取游戏
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- python第三十二课——队列
队列:满足特点 --> 先进先出,类似于我们生活中的买票.安检 [注意] 对于队列而言:python中有为其封装特定的函数,在collections模块中的deque函数就可以获取一个队列对象; ...
- 潭州课堂25班:Ph201805201 django 项目 第三十二课 后台站点管理(课堂笔记)
一.后台站点模版抽取 1.获取静态站点模版 可以使用git clone到本地 git clone https://github.com/almasaeed2010/AdminLTE.git 也可以在g ...
- 第三十二课 linux内核链表剖析
__builtin_prefetch是gcc扩展的,用来提高访问效率,需要硬件的支持. 在标准C语言中是不允许static inline联合使用的. 删除依赖的头文件,将相应的结构拷贝到LinuxLi ...
- python第三十二课——栈
栈:满足特点 --> 先进后出,类似于我们生活中的子弹夹 [注意] 对于栈结构而言:python中没有为其封装特定的函数,我们可以使用list(列表)来模拟栈的特点 使用list对象来模拟栈结构 ...
- JAVA学习第三十二课(经常使用对象API)- 基本数据类型对象包装类
将基本数据类型(8种:int..)封装成对象的优点就是能够在对象中封装很多其它的功能和方法来操控该数据 常见的操作就是:用于基本数据类型与字符串之间的转换 基本数据类型对象包装类一般用于基本类型和字符 ...
- NeHe OpenGL教程 第四十二课:多重视口
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- centos LB负载均衡集群 三种模式区别 LVS/NAT 配置 LVS/DR 配置 LVS/DR + keepalived配置 nginx ip_hash 实现长连接 LVS是四层LB 注意down掉网卡的方法 nginx效率没有LVS高 ipvsadm命令集 测试LVS方法 第三十三节课
centos LB负载均衡集群 三种模式区别 LVS/NAT 配置 LVS/DR 配置 LVS/DR + keepalived配置 nginx ip_hash 实现长连接 LVS是四层LB ...
- NeHe OpenGL教程 第三十六课:从渲染到纹理
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
随机推荐
- python 解析json loads dumps
认识 引用模块 重要函数 案例 排序 缩进参数 压缩 参考 认识 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standa ...
- Linux Purify命令
一.简介 在C/C++的软件开发中,没有任何一种工具可以让你的应用程序避免引入内存问题,但是我们可以使用诸如Purify这样的工具对已经做好了的程序进行内存问题的检查.Purify的强大之处是可以找到 ...
- IPC之PIPE
管道是一种只允许用在有亲属关系的进程间通信的方式,由函数pipe创建一个管道,read,write进行读写操作. #include <unistd.h> ]); 参数pipefd[2]数组 ...
- MBean的学习
参考:http://tuhaitao.iteye.com/blog/786391 这里以MBean对象进行演示向服务器注册,调用的过程. 1.MBean接口,接口名必须以MBean结尾 package ...
- leetcode_438_Find All Anagrams in a String_哈希表_java实现
题目: Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Stri ...
- selenium如何随机选取省份和城市的下拉框的值
1.原始需求,选择省份后,相应的城市会自动加载 2.思路 a.获取下拉框的所有元素个数 b.随机点击0-元素个数之间的某个值 3.代码实现 Random random = new Random(); ...
- jquery 地址栏链接与a标签链接匹配 特效代码总结(二)
如题所述,当出现这样的功能,点击某个链接后,给跳转后的该链接地址添加样式,通过添加class为current来增加特殊样式. 如图所示:点击HTML+css3跳转后,给其添加如图样式: js代码如下: ...
- react webpack.config.js 入门学习
在学习react 的时候必然会用到webpack打包工具,webpack的快速入门另外一篇文章中有记录,这里只记录webpack.config.js文件,因为每个项目下都必须配置,通俗的讲,它的作用就 ...
- android studio没有org.apache.http.client.HttpClient;等包问题 解决方案
以前用Eclipse做Android开发工具一直使用apache的http做网络请求,最近换用了Android studio发现没有办法引用apache的包,下面是我引用的步骤
- Android网络之数据解析----SAX方式解析XML数据
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...