首页 > 代码库 > Web响应的提高
Web响应的提高
想象一下,如果用户在页面上触发一个点击事件,结果反应延迟比较明显,这将是一个令人沮丧的事情。而造成这个问题的原因就是响应延迟。
浏览器UI 线程
大家都知道浏览器的UI线程,大多数浏览器都是一个独立的进程来处理任务。而这个进程被两个任务共享即JavaScript执行任务和UI更新任务,也就是说任何时刻,这两个任务只有一个可以执行。这样就造成JavaScript在执行的时候,用户界面会被“锁定”,不能响应任何操作。所以控制JavaScript的运行时间很重要。
浏览器中,每个JavaScript任务和UI更新任务都会被加入到一个队列中,UI线程会按顺序执行队列中的任务。看下面的实例
上面代码中给button注册了一个click事件,当按钮被点击时会产生两个任务第一个是button外观的改变(button被按下,这是一个UI更新任务),第二个是执行handerClick函数(JavaScript任务),下面是执行的过程
上面可以看出当按钮被点击后,队列中的任务状态,和UI进程的执行过程。
浏览器限制
浏览器对采取了限制,这样可以防止恶意的JavaScript程序无限占用UI进程。这就是常说的长时间脚本限制,其实就是一个脚本定时器。浏览器会设置一个限制,当执行时间达到这个限制,浏览器会终止它。可能会显示一下对话框。
有两种方法测量程序运行的时间,第一种是统计总的JavaScript语句,第二种是统计脚本运行的总时间。Internet Explorer,在第4 版中,设置默认限制为5 百万条语句,Firefox 默认限制为10 秒钟,此限制存放在浏览器的配置设置中(在地址栏中输入about:config)键名为dom.max_script_run_time,Safari 默认限制为5 秒钟,此设置不能改变,但你可以关闭此定时,Chrome 没有独立的长运行脚本限制,替代以依赖它的通用崩溃检测系统来处理此类实例。
多久才算“太久”?
如果整整几秒钟对JavaScript 运行来说太长了,那么什么是适当的时间?事实证明,即使一秒钟对脚本运行来说也太长了。一个单一的JavaScript 操作应当使用的总时间(最大)是100 毫秒。这个数字根据RobertMiller 在1968 年的研究。
更复杂的是有些浏览器在JavaScript 运行时不将UI 更新放入队列。例如,如果你在某些JavaScript 代码运行时点击按钮,浏览器可能不会将重绘按钮按下的UI 更新任务放入队列,也不会放入由这个按钮启动的JavaScript 任务。其结果是一个无响应的UI,表现为“挂起”或“冻结”。
用定时器让出时间片
尽管你尽了最大努力,还是有一些JavaScript 任务因为复杂性原因不能在100 毫秒或更少时间内完成。这种情况下,理想方法是让出对UI 线程的控制,使UI 更新可以进行。让出控制意味着停止JavaScript 运行,给UI 线程机会进行更新,然后再继续运行JavaScript。于是JavaScript 定时器进入了我们的视野。
定时器与UI 线程交互的方式有助于分解长运行脚本成为较短的片断。调用setTimeout()或setInterval()告诉JavaScript 引擎等待一定时间然后将JavaScript 任务添加到UI 列中。例如:
function greeting(){
alert("Hello world!");
}
setTimeout(greeting, 250);
此代码将在250 毫秒之后,向UI 队列插入一个JavaScript 任务运行greeting()函数。在那个点之前,所有其他UI 更新和JavaScript 任务都在运行。请记住,第二个参数指出什么时候应当将任务添加到UI 队列之中,并不是说那时代码将被执行。这个任务必须等到队列中的其他任务都执行之后才能被执行
定时器精度
JavaScript 定时器延时往往不准确,快慢大约几毫秒。仅仅因为你指定定时器延时250 毫秒,并不意味任务将在调用setTimeout()之精确的250 毫秒后加入队列。所有浏览器试图尽可能准确,但通常会发生几毫秒滑移,或快或慢。正因为这个原因,定时器不可用于测量实际时间。
在Windows 系统上定时器分辨率为15 毫秒,也就是说一个值为15 的定时器延时将根据最后一次系统时间刷新而转换为0 或者15。设置定时器延时小于15 将在Internet Explorer 中导致浏览器锁定,所以最小值建议为25 毫秒(实际时间是15 或30)以确保至少15 毫秒延迟。
Web响应的提高