@freeethy
2016-06-17T07:10:28.000000Z
字数 2149
阅读 1460
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);}}}