第六章 Responsive Interfaces 响应接口
- 浏览器在JavaScript运行上采取了限制:调用栈尺寸的限制和运行时间的限制。
每种浏览器的行为大致相同。当脚本执行时,UI 不随用户交互而更新。此时 JavaScript 任务作为用户交互的结果被创建被放入队列,然后当原始JavaScript任务完成时队列中的任务被执行。用户交互导致的UI更新被自动跳过,因为优先考虑的是页面上的动态部分。因此,当一个脚本运行时点击一个按钮,将看不到它被按下的样子,即使它的 onclick 句柄被执行了。尽管浏览器尝试在这些情况下做一些符合逻辑的事情,但所有这些行为导致了一个间断的用户体验。因此最好的方法是,通过限制任何 JavaScript 任务在 100 毫秒或更少时间内完成,避免此类情况出现。这种
测量应当在你要支持的最慢的浏览器上执行
- 解决上面的办法可以使用定时器来分割JavaScript运行的时间。使每部分JavaScript代码可以在100ms内完成。
- 定时器的延迟时间精度不准确,所以不能用定时器来判断精确的时间。
- 一种基本异步代码模式如下:
var todo = items.concat(); //create a clone of the original
setTimeout(function(){
//get next item in the array and process it
process(todo.shift());
//if there's more items to process, create another timer
if(todo.length > 0){
setTimeout(arguments.callee, 25);
} else {
callback(items);
}
}, 25);
下面封装此模式:
function processArray(items, process, callback){
var todo = items.concat(); //create a clone of the original
setTimeout(function(){
process(todo.shift());
if (todo.length > 0){
setTimeout(arguments.callee, 25);
} else {
callback(items);
}
}, 25);
}
- 可通过原生的 Date 对象跟踪代码的运行时间。这是大多数 JavaScript 分析工具所采用的工作方式:
var start = +new Date(),
stop;
someLongProcess();
stop = +new Date();
if(stop-start < 50){
alert("Just about right.");
} else {
alert("Taking too long.");
}
定时器使你的 JavaScript 代码整体性能表现出巨大差异,但过度使用它们会对性能产生负面影响。同一时间只有一个定时器存在,只有当这个定时器结束时才创建一个新的定时器,以这种方式使用定时器不会带来性能问题。
工人线程在 UI 线程之外运行,这种阻塞不会影响 UI 响应。例如:
//inside code.js
importScripts("file1.js", "file2.js");
self.onmessage = function(event){
self.postMessage("Hello, " + event.data + "!");
};
- 工人线程可以另以下任务受益:
- 编/解码一个大字符串
- 复杂数学运算(包括图像或视频处理)
- 给一个大数组排序
Summary 总结
JavaScript和用户界面更新在同一个进程内运行,同一时刻只有其中一个可以运行。 这意味着当JavaScript代码正在运行时,用户界面不能响应输入,反之亦然。有效地管理 UI 线程就是要确保 JavaScript 不能运行太长时间,以免影响用户体验。最后,请牢记如下几点:
- JavaScript 运行时间不应该超过 100 毫秒。过长的运行时间导致 UI 更新出现可察觉的延迟,从而对整体用户体验产生负面影响。
- JavaScript 运行期间,浏览器响应用户交互的行为存在差异。无论如何,JavaScript 长时间运行将导致用户体验混乱和脱节。
- 定时器可用于安排代码推迟执行,它使得你可以将长运行脚本分解成一系列较小的任务。
- 网页工人线程是新式浏览器才支持的特性,它允许你在 UI 线程之外运行 JavaScript 代码而避免锁定 UI。
- 网页应用程序越复杂,积极主动地管理 UI 线程就越显得重要。没有什么 JavaScript 代码可以重要到允许影响用户体验的程度。