6章快速响应的用户界面

  1. 浏览器 UI 线程
  2. 浏览器限制
  3. 多长时间才算太久
  4. 使用定时器让出时间片段
  5. 使用定时器处理数组
  6. 使用定时器分割任务
  7. 记录代码运行时间
  8. Web Worker

基本浏览器就是通过一个单线程来执行 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" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏