JavaScript和用户界面更新在同一个进程中运行,因此一次只能处理一件事情。这意味着当JavaScript代码正在运行时,用户界面不能响应输入,反之亦然。高效地管理UI线程就是要确保JavaScript不能运行太长时间,以免影响用户体验。最后,请牢记如下几点:
- 任何JavaScript任务都不应当执行超过100毫秒。过长地运行时间会导致UI更新出现明显的延迟,从而对用户体验产生负面影响。
/* 使用定时器分割处理长数组,将线程让给UI
* 使用定时器取代循环必须遵守以下两点:
* 1. 处理过程不必须同步。
* 2. 数据不必须按顺寻处理
*/
//正常迭代
for(var i=0, len=items.length;i<len;i++) {
process(items[i]);
}
//定时器方式
var todo = items.concat(); //克隆原数组
setTimeout(function(){
//取得数组的下个元素并处理
process(todo.shift());
//如果还有需要处理的元素,创建另一个定时器
if(todo.length > 0){
setTimeout(arguments.callee,25);
} else {
callback(items);
}
},25);
//功能封装
function processArray(items,process,callback) {
var todo = items.concat(); //克隆
setTimeout(function(){
process(todo.shift());
if(todo.length > 0) {
setTimeout(arguments.callee,25);
} else {
callback(items);
}
},25);
}
- JavaScript运行期间,浏览器响应用户交互的行为存在差异。无论如何,JavaScript长时间运行将导致用户体验变得混乱和脱节。
- 定时器可用来安排代码延迟执行,它使得你可以长时间运行脚本分解成一系列的小任务。
//分割任务
function saveDocument(id){
var tasks = [openDocument,writeText,closeDocument,updateUI];
setTimeout(function(){
//执行下一个任务
var task = tasks.shift();
task(id);
//检查是否还有其他任务
if(tasks.length > 0){
setTimeout(arguments.callee,25);
}
},25);
}
//封装
function multistep(steps,args,callback) {
var tasks = steps.concat();
setTimeout(function(){
//执行下一个任务
var task = task.shift();
task.apply(null,args || []);
//检查是否有其他任务
if(tasks.length > 0){
setTimeout(arguments.callee,25);
} else {
callback();
}
},25);
}
- Web Workers 允许在UI线程外部执行JavaScript代码,从而避免锁定UI。
其他可用worker的任务:
- 编码/解码大字符串。
- 复杂数学运算(包括图像或视频处理)。
- 大数组排序。
/*
* 当解析json需要长时间时使用worker
*/
var worker = new Worker("jsonparser.js");
//数据就位时,调用事件处理器
worker.onmessage = function(event) {
//JSON 结构被回传回来
var jsonData = event.data;
//使用JSON结构
evaluateData(jsonData);
}
//传入要解析的大段JSON字符串
worker.postMessage(jsonText);
//jsonparser.js内部代码
//当JSON数据存在时,该事件处理器会被调用
self.onmessage = function(event) {
//JSON字符串由event.data传入
var jsonData = JSON.parse(jsonText);
//解析
var jsonData = JSON.parse(jsonText);
//回传结果
self.postMessage(jsonData);
}
网友评论