zoukankan      html  css  js  c++  java
  • 使用requestIdleCallback实现一帧执行多任务,

    概念:

    为什么是16.67毫秒:

    这个根据浏览器刷新帧率来定,大多数浏览器的刷新帧率是60Hz,所以1/60 = 0.0166666... (秒)= 16.67(毫秒)

    如果一个任务耗时很长,那么时间用完后会中断该任务吗?

      不会中断该任务,一直到执行完毕为止,所以如果单个任务耗时很长,那么也会造成卡顿。

    测试用例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title></title>
    </head>
    <body>
        
    </body>
    <script>
        function sleep(delay) {
            //在js里面实现睡眠功能
            for (let start = Date.now(); Date.now() - start <= delay;) {}
        }
    
        //fiber 是把整个任务分成很多个小任务,每次执行一个任务
        //执行完成后会看看有没有剩余时间,如果有继续执行下一个任务,如果没有就放弃执行,使用requestIdleCallback将控制权交还给浏览器
        let requesqQueut = [
            () => {
                console.log('第一个任务开始')
                sleep(20)//一帧16.67毫秒(1000/60帧),所以需要把控制权交给浏览器
                console.log('第一个任务结束')
            },
            () => {
                console.log('第二个任务开始')
                sleep(20)
                console.log('第二个任务结束')
            },
            () => {
                console.log('第三个任务开始')
                sleep(20)
                console.log('第三个任务结束')
            },
            () => {
                console.log('第四个任务开始')
                sleep(20)
                console.log('第四个任务结束')
            },
        ]
    
        //告诉浏览器1000毫秒后,即使你没有空闲时间,也得帮我执行,因为我已经等不及了
        window.requestIdleCallback(callBack, {timeOut: 1000})
        //deadLine是一个对象,有两个属性
        //timeRemaining() 返回此帧执行剩余时间
        //didTimeout 此callBack是否超时
        function callBack(deadLine) {
            console.log(`本帧的剩余时间为:${deadLine.timeRemaining()}`)
            //如果此帧=还有剩余时间 或 此时已经超时了
            while ((deadLine.timeRemaining() > 0 || deadLine.didTimeout) && requesqQueut.length > 0) {
                performUnitOfQueueTask()
            }
            
            //说明还有没有执行完的任务
            if (requesqQueut.length > 0) {
                window.requestIdleCallback(callBack, {timeout: 1000})
            }
        }
    
        function performUnitOfQueueTask() {
            requesqQueut.shift()()
        }
    </script>
    </html>

     

     效果展示:

  • 相关阅读:
    MySQL 待解决死锁
    MySQL5.7 服务 crash 后无法启动
    MySQL Group Replication
    MySQL容量规划之tcpcopy应用之道
    Python模块安装路径初探
    MySQL5.7多源复制实践
    Mysql中两个select语句的连接
    ThinkPhp sql语句执行方法
    TP框架如何绑定参数。目的进行ajax验证
    jquery 复合事件 toggle()方法的使用
  • 原文地址:https://www.cnblogs.com/art-poet/p/14769073.html
Copyright © 2011-2022 走看看