Upload
j5726
View
681
Download
7
Embed Size (px)
DESCRIPTION
几个月前做的分享,关于浏览器计时器原理
Citation preview
Timers in BrowserEtai
Content
• 定时器 / 误差
• 优化
• 几个 Bug
Content
• 定时器 / 误差• JS 运行机制
• 时钟精度
• 优化
• 几个 Bug
定时器
setTimeout
返回值 : (number) ID
clearTimeout(ID)
setInterval
返回值 : (number) ID
clearInterval(ID)
浏览器“线程”
浏览器工作进程: 界面渲染
JS 脚本执行
HTTP 连接
JS 引擎:单线程执行
异步事件
鼠标、键盘等事件响应
Ajax 回调
延时 / 定时 (setTimeout/setInterval)
How JavaScript Timers Work / zh
setTimeout vs setInterval
异步回调函数被加入队列等待执行
若回调不能立即执行,将被推迟到下次机会
如果执行延迟过长, setInterval 回调会堆积从而无间隔执行
时钟
硬件时钟: CPU 运行频率
系统时钟: OS 为软件运行提供的时钟 API
时钟精度
系统时钟的最小时间间隔
Windows
默认时钟精度: 15.6ms
multimedia API : 1ms
Mac
默认系统时钟:动态,最小约 4ms
利用 gettimeofday : 1ms
浏览器处理
旧版本:依赖系统时钟
HTML5: 4ms
IE9/Chrome/FF5/safari5.1/Opera11 已实现
电池供电时, Chrome/IE9+ 切换到系统时钟
FF5+/Chrome 11+/IE10+ 空闲标签变为 1000ms
Safari on iOS 5 / Silk on Kindle Fire: 切出应用时冻结
Timer resolution in browsers
影响
setTimeout(fn, 0);
setInterval(fn, 0);
Content
• 误差从哪里来
• 优化• 实现方式优化
• 误差校正
• 几个 Bug
setTimeout or setInterval ?
容易引起堆积的,用 setTimeout 模拟 密集操作 ( 动画等 )
高能耗运算
交互复杂的页面 ( 外部影响 )
BOM 操作
setTimeout(function(){
/* do sth.. */
setTimeout(arguments.callee, 10);
}, 10);
requestAnimationFrame
Mozilla 、 Google 发起
专为网页动画设置
实现有差异,未标准化
时间校正
客户端时间
服务端时间
取客户端时间校正
var timeLeft = 123456ms,
timeStart = new Date().getTime();
// after some time …
var timeNow = new Date().getTime();
timeLeft = timeLeft – (timeNow – timeStart) ;
取客户端时间校正
优点: 简单、高效
缺点: 用户可以修改本地时间造成干扰
取服务器时间校正
发送 Ajax 空响应轮询,取得响应头时间
或搭车其他 Ajax 轮询
空响应 / 取响应头
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {
serverDate = new
Date(xhr.getResponseHeader(‘date’));
//校正}
};
xhr.open('HEAD', '/?'+Math.random());
xhr.send(null);
服务端校准
优点: 准确
缺点 资源消耗
需要考虑网络延迟
Content
• 误差从哪里来
• 优化
• 几个 Bug
当 setInterval 遇到 页面跳转
故障后果
每到 10:00 ,服务器就开始宕机
影响淘江湖几十台服务器
5 天后才找到原因
P1
代码
setInterval(function(){
//…
if(condition){
location.href = ‘xxx’;
}
}, 100)
成因
IE: 页面 unload 之前, interval 持续运行
location.href 本页跳转,接收到新页面内容后,旧页面才 unload
大量用户的页面加载时间大于 100ms
持续发起新的页面跳转,服务器请求拥塞
优化方案
严谨的条件判断
使用 setTimeout 替代
变量覆盖
代码
var a = setTimeout(fn0, 1000);
//…
a = setTimeout(fn1, 3000);
代码
var a = setTimeout(fn0, 1000);
//…
a = setTimeout(fn1, 3000);
//
clearTimeout(a);
成因
setTimeout/setInterval 返回值: (number) ID
覆盖的是 ID ,不是计时器
clearTimeout/clearInterval 参数: (number)
ID
只能清除最后设置的 ID
setTimeout(fn, 0)
作用
将操作脱离队列
等待 (文档内容 )稳定后执行
alert(1);
setTimeout("alert(2)", 0);
alert(3);
场景
操作 DOM ,等待 UI稳定后继续操作 解决 IE6 DOM更新常不同步问题
低优先级操作
替代方案
setImmediate
作用:线程空闲时执行操作
微软提出,尚未纳入标准
var id = setImmediate(function(){
//do sth
});
替代方案
web workers : HTML5 多线程方案
主线程 :
var worker = new Worker( url )
worker.postMessage( data )
worker.onmessage
worker.terminate()
新线程 postMessage( data )
onmessage
web workers 的局限
不能跨域加载 JS文件
worker 代码不能直接访问 DOM
浏览器实现不一致
Thanks~
将图片拖动到占位符,或单击添加图标