@freeethy
2016-06-17T15:10:28.000000Z
字数 2149
阅读 1310
high
performance
javascript
setTimeout
浏览器限制了javascript任务运行的时间。
当浏览器的长时间运行脚本限制被触发时,会弹出一个对话框提示用户,而不管页面中其他的错误捕获代码。 如果你的脚本在任意浏览器中触发次对话框,这意味着脚本花了太多时间来完成任务。它还表明用户浏览器在javascript继续运行中无法响应用户输入。
单个javascript操作花费的总时间(最大值)不应该超过100ms。
有些浏览器在javascript运行时不会把UI更新任务加入队列。最终结果是一个失去响应的UI,表现为“挂起”或“假死”。
一些复杂的js任务不能在100毫秒或更短时间内完成,这个时候最理想的方法是让出UI线程的控制权,使得UI可以更新。
setTimeout 和 setInterval的第二个参数表示任务何时被添加到UI队列,而不是一定会在这段时间后执行,这个任务会等待队列中其他所有任务执行完毕才会执行。
无论发生法何种情况,创建一个定时器会造成UI线程暂停,如同它从一个任务切换到下一个任务。因此,定时器代码会重置所有相关的浏览器限制,包括长时间运行脚本定时器。此外,调用栈也在定时器的代码中重置为0.这一特性使得定时器成为长时间运行javascript代码理想的跨浏览器解决方案。
如果UI队列中已经存在由同一个setInterval()创建的任务,那么或许任务不会被添加到UI队列中。
在Windows系统中定时器分辨率为15ms,也就是说一个延时15ms的定时器将根据最后一次系统时间刷新而转换为0或15。设置定时器延时小于15蒋慧导致IE锁定,所以延迟的最小值建议为25ms(实际时间是15或30)以确保至少有15ms的延迟。
是否可以用定时器取代循环的两个决定性因素:
把循环的工作分解到一系列定时器中
function processArray(items, process, callback) {
var todo = items.cancat(); //克隆原数组
setTimeout(function() {
process(todo.shift());
if (todo.length > 0) {
setTimeout(arguments.callee, 25);
} else {
callback(items);
}
}, 25);
}
使用定时器处理数组的副作用是处理数组的总时长增加了。这是因为在每一个条目处理完成后UI线程会空闲出来,并且在吓一条目开始处理之前会有一段延时。
分割任务
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)
}
每50ms判断,每次间隔运行多次
function timedProcessArray(items, process, callback) {
var todo = items.cancat(); //克隆原数组
setTimeout(function() {
var start = +new Date();
do {
process(todo.shift());
} while (todo.length > 0 && (+new Date() - start) < 50)
if (todo.length > 0) {
setTimeout(arguments.callee, 25);
} else {
callback(items);
}
}, 25);
}
function addHandler(target, eventType, handler) {
if (target.addEventListener) {
addHandler = function(target, eventType, handler) {
target.addEventListener(eventType, handler, false);
}
} else {
addHandler = function(target, eventType, handler) {
target.attachEvent("on" + eventType, handler);
}
}
}