1. 定时器基础
定时器与UI线程的交互方式有助于把长时间运行脚本拆分成为较短的片段。
任何JavaScript任务都不应当执行超过100ms。过长的运行时间会导致UI更新出现明显的延迟。
setTimeout(func, 200);
第二个参数表示任务func何时被添加到UI队列的时间,而不是一定会在这段时间后执行。并且250ms是在定时器被调用时开始计算的。
无论发生什么情况,创建一个定时器会造成UI线程暂停,如同它从一个任务切换到下一个任务。因此,定时器代码会重置所有相关的浏览器限制,包括长时间运行脚本定时器、调用栈被重置为0,这一特性使得定时器成为长时间运行JS代码理想的跨浏览器解决方案。
2. 定时器精度
JavaScript定时器延迟通常不太精准,相差大约几毫秒。
设置定时器延迟小于15ms会导致IE锁定
延迟的最小值建议为25ms以确保至少有15ms延迟
3. 使用定时器处理数组
/** * 定时器处理数组 * @param {Array} array 待处理的数组 * @param {Function} process 处理数组的函数 * @param {Function} callback 数组处理完后调用的函数 */ function processArray(array, process, callback) { var cloneArray = array.concat(); //克隆数组 setTimeout(function() { process(cloneArray.shift()); //处理元素 if(cloneArray.length > 0) { setTimeout(arguments.callee, 25); }else { callback(); } }, 25); } //--------------------- var arr = [1,2,3,4,5,6]; function process(value) { console.log(value); } processArray(arr, process, function() { console.log('Done!'); });
4. 分割任务
通常可以被把一个任务分解成多个子任务。如果一个函数运行时间太长,那么检查一下是否可以把它拆分成为一系列在较短时间内完成的子函数。
function saveDocument(id) { openDocument(id); writeText(id); closeDocument(id); updateUI(id); //将成功信息更新至界面 } 可用定时器去执行 function multistep(steps, args, callback) { var tasks = steps.concat(); //克隆数组 setTimeout(function() { var task = tasks.shift(); task.apply(null, args || []); //检查是否还有其他任务 if(tasks.length > 0) { setTimeout(arguments.callee, 25); }else { callback(); } }, 25); } //------------------- test ----- function saveDocument(id) { var tasks = ['openDocument', 'writeText', 'closeDocument', 'updateUI']; multistep(tasks, [id], function() { alert('Done'); }); }
5. 记录代码运行时间
如果按照每次执行一个任务建立定时器效率不高,可以按照执行时间来判断是否建立定时器
function timedProcessArray(array, process, callback) { var cloneArray = array.concat(); //克隆数组 setTimeout(function() { var startTime = +new Date(); //处理数组50ms后再建立下一个定时器 do{ process(cloneArray.shift()); //处理元素 }while(clone.length>0 && (+new Date()-startTime<50)) if(cloneArray.length > 0) { setTimeout(arguments.callee, 25); }else { callback(); } }, 25); }
6. 定时器与性能
建议只创建一个独立的定时器,每次可以执行多个操作