页面快速响应(一)

170 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

当我们在浏览网页时是不是经常会碰到这种情况--点击某个按钮缺没有响应,等他开始有动静的时候鼠标已经点击了关闭网页。这个问题源头在于那些事务性的 Web 应用,导致我们现在提交表单时几乎总会遇到 “请不要重复提交” 的信息。用户会本能的去重复尝试那些没有带来明显变化的行为,这对用户体验非常的不好,所以确保 Web 应用的响应速度是一个非常重要的性能关注点。

浏览器UI 线程

用于执行 Javascript 和更新用户节面的进程通常被称为 "浏览器UI线程"。UI 线程的工作给予一个简单的队列系统。任务会被保存到队列中直到进程空闲,一旦空闲队列中的下一个任务就会被重新提取出来并运行。这些任务要么运行的是 JS 代码,要么是执行 UI 更新,包括重绘和重排。最重要的是每次输入都可能会导致一个或多个任务被加入进程。

<body>
    <button onclick="handleClick()">点击</button>
    <script>
        function handleClick(){
            var div = document.createElement("div");
            div.innerHTML = "点击";
            document.body.appendChild(div);
        }
    </script>
</body>

当实例中的按钮被点击时,它会触发 UI 线程来创建两个任务并添加到队列中。第一个任务是更新按钮的UI,它需要改变外观以指示他被点击了,第二个任务是执行 Javascript,包含 handleClick() 中的代码,唯一被运行的代码就是这个方法和所有被他调用的方法。假设 UI 线程出于空闲状态,第一个任务被提取出来执行。在运行过程中,handleClick() 创建了一个新的 <div> 元素并把它附加在 <body> 元素末尾,这实际上引发了另一次 UI 变化。这意味着在 JavaScript 运行过程中,一个新的 UI 更新任务被添加在队列中,当 JavaScript 运行完之后, UI 还会再更新一次。

当所有 UI 线程任务都执行完毕,进程进入空闲状态,并等待更多任务加入队列。如果用户试图在任务运行期间与页面交互,不仅没有即时的 UI 更新,甚至可能新的 UI 更新任务都不会被创建并加入队列。事实上,大多数浏览器在 JavaScript 运行时会停止吧新任务加入 UI 线程队列中,也就是说 JavaScript 任务必须尽快结束,以避免用户体验造成不良影响。