没用系列之定时器

最近有个乱七八糟的产品,又加了个乱七八糟的需求,结果还被怼了乱七八糟,阿西吧! 在页面设置两个定时器,一个倒计时,另一个轮询,有冲突(臆想)。 基础 setTimeout 最基础的定时器是 setTimeout,指定 xx ms 后执行。 来看它的一个缺陷: for () { // 运行了 1s } // 指定 100ms 后执行 setTimeout('console.log(1)', 100); 打印日志的时间在 1s 后,而不是我们预期的 100ms。 众所周知 js 是单线程的,在线程被占用的情况下,无法进行另一个操作,只能加入到执行队列中,而一旦线程空闲时,会立即执行队列中的操作。 因此,setTimeout 的执行时间是不太精确的。 重复 setInterval setInterval 主要用来重复执行,指定 xx ms 间隔。 它是在各个时间点加入到执行队列中,等进程空闲后执行。可能出现某个间隔被跳过的情况: setInterval(function longTime() { for () { // 运行了 300ms } }, 100); longTime 运行期间,其它 longTime 副本也被加入到队列中,多个只执行最先加入的那个,其它将被跳过。 这个小缺陷可以用高级点的技巧避免: setTimeout(function foo() { // 一些操作 // 递归,做到类似 setInterval 的效果 // 且比 setInterval 更可靠,保证了间隔不被跳过 setTimeout(foo, 100); }, 100); 应用 定时器的延迟执行功能,可应用到许多场景,例如倒计时等等。更多的是性能优化这一块。 数组分块 Yielding Processes 假设有这样的场景: const arr = new Array(1000); for (let i = 0; i < arr.length; i++) { // 操作数组的每一项,同步的 // 运行了 100ms } // 总共耗时 1000x0.1 = 100s 上面的场景,界面在 100s 内都无响应,因为 js 线程一直被占用,无法执行其它操作。 使用定时器把数组分成一块一块处理: const arr = new Array(1000); const chunkSize = 1; // 分块大小 setTimeout(function foo() { const arrChunk = arr.splice(0, chunkSize); // 操作分块后的数组 arrChunk // 运行了 100ms * chunkSize if (arr.length > 0) { // 100ms 的缓冲期,让界面不至于失去响应 setTimeout(foo, 100); } }, 100); 节流和防抖 throttle & debounce 节流和防抖两个概念太相似了,每次都会把它俩搞混。。。都是减少触发频率,提高性能,最主要的差别应该是触发时间。 节流触发时间在前。类似 setInterval 的执行机制,触发多次时,在指定的时间间隔内,只有第一次的才会执行,其它的跳过(手动)。 防抖触发时间在后。与 setTimeout 类似,延迟执行,触发多次时,只执行最后一个,其它的被清除(手动)。 应用场景上也能混用,,,大概了解下就行了 // 大多用在 scroll 上的节流 // 也可以使用 px 单位,比如 10px HTMLElement.addEventListener('scroll', function throttle() { const ts = Date.now(); // 上次调用时间过了 100ms if (ts - lastInvokeTs > 100) { lasInvokeTs = ts; // 一些操作 } }); // 大多用在 keyup、resize 上的防抖 HTMLElement.addEventListener('keyup', function debounce() { // 延迟到触发时 100ms 后 clearTimeout(timer); timer = setTimeout(function () { // 一些操作 }, 100); }); 针对 Css 渲染方面的节流可以考虑原生更流畅的 API requestAnimationFrame: HTMLElement.addEventListener('scroll', function foo() { if (!changing) { requestAnimationFrame(function () { // 一些操作 changing = false; }); } changing = true; }); css-tricks 上更好的一篇解释防抖节流的文章。 The End 一般来说页面里同时设置几个定时器问题不大,js 的执行速度很快,误差也大不到哪去,况且 ms 级别的误差也感觉不到。 节流和防抖还是比较混,阿西吧!


JavaScript全屏阅读

上一篇:钢铁是怎样炼成的

下一篇:打酱油

Ctrl + Enter