页面快速响应(二)

278 阅读3分钟

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

浏览器限制

浏览器限制了 JavaScript 任务的运行时间。这种限制是有必要的,它确保了某些恶意代码不能通过永不停止的密集操作锁住用户的浏览器或计算机。此类限制分两种:调用栈大小限制和长时间运行脚本限制。长时间运行脚本限制有时被称为长时间运行脚本定时器或失控脚本定时器,但其基本原理是浏览器会记录一个脚本的运行时间,并在达到一定限度时终止它。

有两种方法可以度量脚本运行了多“长”。第一种是记录自脚本开始以来执行的语句的数量,这种方法意味着脚本在不同的机器上可能会有不同的运行时间,因为可用内存和CPU速度会影响单个语句的执行时间。第二种方法是记录脚本执行的总时才,在指定时间内可运行的脚本数量也因用户的机器性能而有所差异,但是到达执行时间后,脚本会停止运行。

时才限度

浏览器允许脚本持续运行好几秒,但这并不意味着你也允许它这样做。事实上,为了更好的用户体验,你的JavaScript 代码运行的持续时间应当远远小于浏览器的限制。

如果对运行 JavaScript 而言,几秒钟算久的话那么多长时间才算合适呢?事实证明,哪怕是一秒钟对于脚本运行而言也太长了。单个 JavaScript 操作花费的总时间不应该超过100毫秒。如果界面在100毫秒内响应用户输入,用户会认为自己在 “直接操作界面中的对象”。 超过100毫秒意味着用户感到自己与界面失去联系。

更复杂的情况是有些浏览器在 JavaScript 运行时不会把 UI 更新任务加入队列。假如你在某些 JavaScript 代码运行时点击按钮,浏览器可能不会把重绘按钮状按下状态的任务或点击按钮启动的新 JavaScript 任务加入对列。最终结果是一个失去响应的 UI,表现为 挂起假死

各种浏览器的行为大致相同,当脚本执行时, UI 不随用户交互而更新。执行时间段内用户交互行为所引发的 JavaScript 任务被加入队列中,并在最初的 JavaScript 任务 完成后依次执行。而这段时间内由用户交互行为引发的 UI 更新会被自动跳过,因为页面中的动态变化部分会优先考虑。因此,在一个脚本运行期间点击一个按钮,将无法看到它被按下的样式,尽管它的 onClick 事件处理器会被执行。

所以为了改善用户体验限制所有 JavaScript 任务在100毫秒或更短的时间内完成。

让出时间片段

尽管你尽量避免,但是还是会有一些复杂的 JavaScript 任务不能在 100毫秒 内完成。这个时候最理想的办法是让出 UI 线程的控制权,使得 UI 可以更新。让出控制器意味着停止执行 JavaScript,使得 UI 更新线程有机会执行。而这一方法需要用到 定时器

我们通常会把一个任务分解成一系列子任务。如果一个函数运行时间太长,那么检查一下是否可以把它拆分为一系列能在较短时间内完成的子函数。往往可以把一行代码简单地看成一个原子任务,即使是多行代码也可以组合起来构成一个独立的任务。