编程基本原则-时间切片

175 阅读2分钟

时间切片是一种将长时间运行的任务分解为可中断块的技术。

image.png

优势

  • 提高应用程序的响应性和用户交互性
  • 保证任务间的相对优先级
  • 支持任务取消和暂停,提高应用程序的灵活性和可控性
  • 可以从任务失败中恢复,并从中间继续执行

浏览器

因为浏览器环境的 渲染JavaScript互斥的,所以长时间的 Javascript 任务,导致页面 卡顿 或者失去响应,会给用户带来极差的用户体验。

使用 时间切片 技术可以将长时间运行的任务分解为 小块 ,在块之间运行其他任务,从而提高应用程序的响应性,让用户获得更加流畅的交互体验。

API

浏览器为开发者提供以下几个 API 来避免长任务带来的阻塞效果。

案例

React

当组件渲染过程中遇到复杂的计算大量的数据加载或者耗时的操作时,会导致渲染线程被阻塞,从而导致页面卡顿、用户体验变差。

为了优化大型应用程序的性能和用户体验,React 引入了时间切片(Time Slicing)

源码中使用 MessageChannel 这个API来实现任务切片。详细可以看它的源码

拓展

为什么不优先使用 setTimeout

React 任务调度器中优先使用 MessageChannel 而不是 setTimeout 的原因是因为 MessageChannel 具有更好的性能和精度,可以达到纳秒级别。

setTimeout 的最小延迟时间为 4 毫秒,每个任务都使用 setTimeout,则会导致整个过程更多延迟。

oss

文件过大网络环境较差文件大小不确定时,为了更快,更稳定的提高上传能力。

OSS提供分片上传功能,可以将待上传的文件分成多个碎片(Part)分别上传,上传完成之后再调用,最终将每一部分组合成一个大的文件。

示例

下面是一个以渲染长列表为例的 DEMO 在线

我们可以明显看到长任务渲染有渲染的延迟,时间切片渲染则可以直接看到渲染结果。

<!DOCTYPE html>
<html>
  <head>
    <title>时间切片</title>
    <meta charset="UTF-8" />
    <style>
      #container div {
        height: 20px;
        margin-bottom: 6px;
        background-color: aquamarine;
      }
    </style>
  </head>
  <body>
    <button onclick="syncRender()">长任务渲染</button>
    <button onclick="timeSliceRender()">时间切片渲染</button>
    <button onclick="reset()">重置</button>

    <div id="container"></div>
    <script type="text/javascript">
      let i = 0;
      let rendering = false;
      const max = 200000;
      const stepMax = max / 20;
      const container = document.getElementById("container");

      function syncRender() {
        while (i < max) {
          const div = document.createElement("div");
          container.append(div);
          i++;
        }
      }

      function timeSliceRender() {
        rendering = true;
        setTimeout(() => {
          let j = 0;
          while (j < stepMax && i < max) {
            const div = document.createElement("div");
            container.append(div);
            i++;
            j++;
          }

          if (i < max) {
            timeSliceRender();
          } else {
            rendering = false;
          }
        });
      }

      function reset() {
        if (rendering) {
          alert("渲染中,稍等下");
        }
        i = 0;
        container.innerHTML = "";
      }
    </script>
  </body>
</html>

总结

时间切片是一种编程技术,它允许我们将大型、复杂的任务拆分成更小的片段,并在这些片段之间插入其他任务,以使我们的程序能够更加响应高效