专栏首页亦枫的大佬之路JavaScript中的时间分片(Time Slicing)

JavaScript中的时间分片(Time Slicing)

根据W3C性能的介绍,超过50ms的任务就是长任务。

当延迟超过100ms,用户就会察觉到轻微的延迟。所以为了避免这种情况,我们可以使用两种方案,一种是Web Worker,另一种是时间切片(Time Slicing)。

时间分片(Time Slicing)

时间分片的核心思想是:如果任务不能在50毫秒内执行完,那么为了不阻塞主线程,这个任务应该让出主线程的控制权,使浏览器可以处理其他任务。让出控制权意味着停止执行当前任务,让浏览器去执行其他任务,随后再回来继续执行没有执行完的任务。

所以时间分片的目的是不阻塞主线程,而实现目的的技术手段是将一个长任务拆分成很多个不超过50ms的小任务分散在宏任务队列中执行。

时间分片是一项使用得比较广的技术方案,它的本质就是将长任务分割为一个个执行时间很短的任务,然后再一个个地执行。

这个概念在我们日常的性能优化上是非常有用的。

例如当我们需要在页面中一次性插入一个长列表时(当然,通常这种情况,我们会使用分页去做)。

如果利用时间分片的概念来实现这个功能,我们可以使用requestAnimationFrame+DocumentFragment。

这里有两个DEMO,大家可以对比下流畅程度:

未使用时间分片:

<style>
    * {
        margin: 0;
        padding: 0;
    }
    .list {
        width: 60vw;
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
    }
</style>
<ul class="list"></ul>
<script>
    'use strict'
    let list = document.querySelector('.list')
    let total = 100000
    for (let i = 0; i < total; ++i) {
        let item = document.createElement('li')
        item.innerText = `我是${i}`
        list.appendChild(item)
    }
</script>

使用时间分片:

<style>
    * {
        margin: 0;
        padding: 0;
    }
    .list {
        width: 60vw;
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
    }
</style>
<ul class="list"></ul>
<script>
    'use strict'
    let list = document.querySelector('.list')
    let total = 100000
    let size = 20
    let index = 0
    const render = (total, index) => {
        if (total <= 0) {
            return
        }
        let curPage = Math.min(total, size)
        window.requestAnimationFrame(() => {
            let fragment = document.createDocumentFragment()
            for (let i = 0; i < curPage; ++i) {
                let item = document.createElement('li')
                item.innerText = `我是${index + i}`
                fragment.appendChild(item)
            }
            list.appendChild(fragment)
            render(total - curPage, index + curPage)
        })
    }
    render(total, index)
</script>

没有做太多的测评,但是从用户视觉上的感受来看就是,第一种方案,我就是想刷新都要打好几个转,往下滑的时候也有白屏的现象。

除了上述的生成DOM的方案,我们同样可以利用Web Api requestIdleCallback 以及ES6 API Generator]来实现。

具体实现如下:

<style>
    * {
        margin: 0;
        padding: 0;
    }
    .list {
        width: 60vw;
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
    }
</style>
<ul class="list"></ul>
<script>
    'use strict'
    function gen(task) {
      requestIdleCallback(deadline => {
        let next = task.next()
        while (!next.done) {
          if (deadline.timeRemaining() <= 0) {
            gen(task)
            return
          }
          next = task.next()
        }
      })
    }
    let list = document.querySelector('.list')
    let total = 100000
    function* loop() {
      for (let i = 0; i < total; ++i) {
        let item = document.createElement('li')
        item.innerText = `我是${i}`
        list.appendChild(item)
        yield
      }
    }
    gen(loop())
</script>

使用时间切片的缺点是,任务运行的总时间变长了,这是因为它每处理完一个小任务后,主线程会空闲出来,并且在下一个小任务开始处理之前有一小段延迟。 但是为了避免卡死浏览器,这种取舍是很有必要的。

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!
本文分享自作者个人站点/博客:https://blog.csdn.net/liuyifeng0000复制
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • 什么是时间分片(Time Slicing)?

    所以为了避免这种情况,我们可以使用两种方案,一种是Web Worker,另一种是时间切片(Time Slicing)。

    前端劝退师
  • 什么是时间分片(Time Slicing)?

    所以为了避免这种情况,我们可以使用两种方案,一种是Web Worker,另一种是时间切片(Time Slicing)。

    陈大鱼头
  • 【优化】514- 如何使页面交互更流畅

    本篇是基于 FDCon2019 上《让你的网页更丝滑by刘博文》的复盘文。该课题也是博主感兴趣的领域, 后续会结合 React 的 Schedule 与该文进行...

    pingan8787
  • 如何使页面交互更流畅

    本篇是基于 FDCon2019 上《让你的网页更丝滑by刘博文》的复盘文。该课题也是博主感兴趣的领域, 后续会结合 React 的 Schedule 与该文进行...

    牧云云
  • 针对5G无线电接入网络切片的洪泛攻击的对抗机器学习

    网络切片将网络资源作为5G无线电接入网络(RAN)的虚拟资源块(RB)进行管理。每个通信请求都具有体验质量(QoE)要求,例如吞吐量和等待时间/最后期限,这可以...

    YH
  • 前端每周清单第 54 期: SwiftNIO, 自定义 vue-router, Web 缓存与 GraphQL 必知必会

    前端每周清单专注大前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点;分为新闻热点、开发教程、工程实践、深度阅读、开源项目、巅峰人生等栏目。欢迎关...

    王下邀月熊
  • 软件定义5G —— Network slicing

    SDNLAB
  • Java中时间类中的Data类与Time类

    上面我们了解了Date类,我们知道,他是一个比较老的类,且不是线程安全的,所以,我们目前基本上是使用他的升级版LocalDate。

    JanYork_小简
  • Qnext大会 | App Slicing在携程APP上的实践

    原创专栏|祁一鸣 ? 2016年4月加入携程, 任机票研发部技术专家。毕业于美国常春藤名校Dartmouth College本科,曾先后在硅谷的Oracle, ...

    携程技术
  • Python Python中的时间包2 time模块

    Zkeq
  • CVPR2021|用于立体匹配的可学习双边网格

    高精度的实时立体匹配网络是时下研究的一个热点,它在自动驾驶、机器人导航和增强现实等领域中有着广泛的应用。虽然近年来对立体匹配网络的研究已经取得了显著的成果,但要...

    3D视觉工坊
  • 【独家】周志华教授gcForest(多粒度级联森林)算法预测股指期货涨跌

    公众号特约编辑 / 一心想错 / 独家 gcForest Algorithm 对于周志华教授的文章,网上已经有人做出很详细的解释啦。我们对论文进行简单描述之后,...

    量化投资与机器学习微信公众号
  • 谈谈新的 React 新的生命周期钩子

    在 React 16.3 中,Facebook 的工程师们给 React 带来一系列的新的特性,如 suspense 和 time slicing 等,这些都为...

    IMWeb前端团队
  • CiteSpace小白入门级宝典

    CiteSpace简单来说,它一款通过将国内外文献进行可视化分析来帮助你了解一门学科前世今生的软件。

    算法与编程之美
  • php中的时间戳与javascript中的时间戳的比较

    php中的时间戳与javascript中的时间戳的比较,本质上看,它们是一样的东西,但如果二者要进行相等比较的时候,还是有点不同的,稍不注意,就会误入歧途,所以...

    风柏杨4711
  • Vue.js 的九个性能优化技巧

    这篇文章主要参考了 Vue.js 核心成员Guillaume Chau在 19 年美国的 Vue conf 分享的主题:9 Performance secret...

    美食江湖
  • 25个超有用的Python代码段

    Python是一种通用的高级编程语言。用它可以做许多事,比如开发桌面 GUI 应用程序、网站和 Web 应用程序等。

    逆锋起笔
  • 25个有用的 Python 代码段

    作为一种高级编程语言,Python 还可以让你通过处理常见的编程任务来专注应用程序的核心功能。并且,编程语言的简单语法规则进一步简化了代码库的可读性和应用程序的...

    用户6859632

扫码关注云+社区

领取腾讯云代金券