6章快速响应的用户界面
基本浏览器就是通过一个单线程来执行 JS 代码和更新的,所以当 JS 代码执行的时候,用户界面其实是属于锁定的状态的,所以管理好 JS 的运行时间很重要。
浏览器 UI 线程
就是一个简单的队列系统。一旦空闲,队列中的下一个任务就会被重新提取出来并运行。这些任务包括运行 JS 代码,还有 UI 的更新,包括重绘和重排。每一次输入可能会导致一个或者多个任务被加入队列。事实上,大多数浏览器在 JS 执行的时候回停止把新任务加入到 UI 线程中,JS 代码必须尽快结束。
浏览器限制
浏览会限制 JS 运行,一个是调用栈的大小以及长时间运行脚本限制。(各个浏览器的长时间限制不同,IE 是超过了 500 万条,ff 是 10 秒,Safari 是 5 秒,chrome 是崩溃检测)
多长时间才算太久
事实上,我们应该控制在 100ms 以内,因为如果运行时间超过了 100ms,用户就能够感受到。
使用定时器让出时间片段
有时我们已经尽力压缩过了,但是 js 还是运行了不止 100ms,我们可以设置定时器来让出 UI 线程的控制权,然 UI 有机会更新。
setInterval 和 setTimeout 的区别在于除了前者会重复执行之外。还有一点很重要:如果 UI 队列已经存在同一个 setInterval 创建的任务,那么后续任务不会被添加到 UI 队列中。
使用定时器处理数组
当我们必须处理一些超大量的数据的时候,我们可以使用定时器来分解执行,防止对 UI 线程锁住太长的时间,比如:
var tudo = items.concat();
setTimeout(function() {
process(tudo.shift());
if (tudo.length > 0) {
setTimeout(arguments.callee, 50);
} else {
callback();
}
}, 50);
//这里用arguments.callee来指代现在正在运行的匿名函数,这个东西挺管用的,但是ES5严格模式不支持
使用定时器分割任务
当一个任务执行时间太长太复杂的时候,我们可以把他分割成很多的子任务,然后通过定时器的方法来执行,防止主 UI 线程被锁的太久。
记录代码运行时间
我们可以通过记录代码的运行时间来智能
的决定执行几次任务
function timeProcess(array, process, callback) {
var tudo = array.concat();
setTimeout(function() {
var start = +new Date();
do {
process(tudo.shift());
} while (tudo.length > 0 && +new Date() - start < 50);
if (tudo.length > 0) {
setTimeout(arguments.callee, 25);
} else {
callback();
}
}, 25);
}
这个使用方法好机智啊
Web Worker
这里其实自己已经研究过了,参见学习笔记
使用还算简单,功能也蛮强大,就是支持的情况太差了,IE10 才支持
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 981909093@qq.com
文章标题:6章快速响应的用户界面
文章字数:734
本文作者:泽鹿
发布时间:2019-08-28, 16:45:23
最后更新:2019-08-28, 16:45:23
原始链接:http://panyifei.github.io/2019/08/28/读书笔记/高性能Javascript/6章快速响应的用户界面/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。