• 使用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>

     

     效果展示:

  • 相关阅读:
    快速创建一个 Servlet 项目(1)
    快速创建一个 Servlet 项目(2)
    多级派生情况下派生类的构造函数
    最近看了点C++,分享一下我的进度吧!
    进程同步&进程间通信
    multiprocess模块
    进程
    网络编程之socket
    网络通信原理
    网络通信的流程 | 初始socket
  • 原文地址:https://www.cnblogs.com/art-poet/p/14769073.html
Copyright © 2020-2023  润新知