美文网首页
高性能 JavaScript - 快速响应的用户界面

高性能 JavaScript - 快速响应的用户界面

作者: VioletJack | 来源:发表于2019-03-08 20:59 被阅读0次

    这几天分享一下我看《高性能 JavaScript》的学习笔记,希望能对大家有所帮助。

    共用 UI 线程

    关于用户界面的相应,最重要的一个知识点是:浏览器中更新 UI 和执行 JavaScript 是共用一个线程的!

    当 JavaScript 运行中,线程会停止把新任务加入线程。所以当某个 JavaScript 长时间运行时,页面 UI 没有反应。就是因为 UI 更新的任务没有加入到线程中。

    浏览器对于脚本是有一定的显示的:调用栈大小限制和长时间运行脚本限制。

    如果遇到调用栈大小限制错误,会在控制台输出错误。这类错误可以使用 try ... catch 来捕获。如果遇到长时间运行脚本限制,浏览器会显示页面无响应的界面。这个界面无法被 JavaScript 处理。我们应当避免这两种限制报错的情况发生。

    JavaScript 最佳运行时长

    经过大量测试得出,单条 JavaScript 操作时间超过 100 毫秒,会让用户感觉到失去了对界面的控制。所以想要优化界面响应速度应当让单个 JavaScript 操作花费小于 100 毫秒。

    而且当单个 JavaScript 操作时间超过 100 毫秒,UI 更新任务可能会无法加入线程,出现“假死”的情况。

    定时器

    虽然理想中所有 JavaScript 操作时间都要小于 100 毫秒,但是如果真的有复杂操作需要花费很长时间怎么办呢?可以使用定时器异步执行。

    定时器代码会重置所有相关的浏览器限制,包括长时间运行脚本限制。

    定时器并不准确

    虽然定时器会定义一个时间,在这个时间之后异步执行。但其实从执行到 setTimeout() 方法到执行函数的时间会大于我们定义的时间间隔。因为执行 setTimeout() 方法需要时间;而且 setTimeout 不能保证间隔时间后能够立即执行,如果有 JavaScript 操作正在执行,那么回调函数的执行会延后。

    定时器处理循环

    如果循环中 JavaScript 操作时间很长,就可以使用 setTimeout 定时器来执行。

    var button = document.getElementById("my-button")
    button.onclick = function () {
        oneMethod()
        setTimeout(function () {
            document.getElementById("notice").style.color = "red";
        }, 250);
    }
    

    为什么是 250 毫秒的间隔?因为要让 UI 更新留出时间。

    如果循环内的操作执行时间太长,可以分步骤分隔任务,再用定时器封装按步骤执行。

    如何更准确的记录代码运行时间?

    var start = +new Date()
    var end = +new Date()
    console.log(end - start)
    

    限制高频率重复定时器的数量,可以使用重复定时器 setInterval() 来替代。

    Web Workers

    Web Worker 使 JavaScript 可以在 UI 线程之外运行代码,它有自己的运行环境。

    如何使用?

    我们无法从 JavaScript 代码中创建 web worker,必须在外部新建一个 .js 文件,并使用 API 创建 Web Worder。

    var worker = new Worker('code.js')
    

    创建了 WebWorker 其实是提供了一个新线程和一个 WebWorker 运行环境。

    WebWorker 通过 importScript() 方法加载外部 JavaScript 文件到 WebWorker 运行环境,加载行为是阻塞性的。但不会影响 UI 线程。

    WebWorker 非常适合处理复杂的、无 UI 交互的、纯数据的脚本。它不会占用 UI 线程不会影响 UI 的更新。

    WebWorker 通信

    WebWorker 运行在独立线程和运行环境中,所以它需要和 UI 线程通信交互。它们唯一的通信方式就是消息机制。

    在主要代码中的通信方式如下:

    var worker = new Worker("code.js")
    // 接收 worker 的消息
    worker.onmessage = function(event){
        alert(event.data)
    }
    // 向 worker 发送消息
    worker.postMessage("Nicholas");
    

    而在 worker 中的通信方式其实也差不多:

    // 在 worker 中接收消息
    self.onmessage = function(event) {
        // 在 worker 中发送消息
        self.postMessage("hello " + event.data + "!");
    }
    

    应用场景

    下面是一些 WebWorker 的应用场景:

    • 解析/解码大字符串
    • 复杂数学运算
    • 大数组排序
    • 其他超过 100 毫秒的行为都可以考虑用 WebWorker 或者 定时器来优化 UI 响应。

    小结

    • 执行 JavaScript 操作和 UI 更新共用一个 UI 线程。
    • 最佳响应时间是小于 100 毫秒。
    • 超过 100 毫秒的 JavaScript 操作可以使用定时器来异步执行。
    • WebWorker 会提供新的线程和运行环境来执行 JavaScript,非常适合复杂、无 UI 交互、纯数据的脚本执行。

    快速的用户界面响应速度能够非常好的提高用户体验,是非常重要的。可以从上面的内容中优化一下自己的代码。

    相关文章

      网友评论

          本文标题:高性能 JavaScript - 快速响应的用户界面

          本文链接:https://www.haomeiwen.com/subject/msqnuqtx.html