3. 实现任务调度器

146 阅读1分钟

目标:实现任务调度器

为什么要实现任务调度器

  • dom特别大的时候会造成渲染卡顿
  • 看一个demo,代码如下,卡顿原因,js执行是单线程的,while循环逻辑会阻塞后面渲染

    • main.js
    const el = document.createElement("div");el.innerHTML = "I love eat cakes";
    ​
    document.body.appendChild(el);
    let i = 0
    while (i < 100000000000) {
      i++
    }
    
    • index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Demo</title>
    </head>
    <body>
      <script type="module" src="main.js"></script>
    </body>
    </html>
    

之前写的render函数其实也是一个道理

  • 是一个递归,如果树非常大就会一直render

如何解决

  • 使用分治的思想去拆分,比如一个任务只渲染两个dom树,直 到渲染结束
  • 1746687124269.png
  • 借助浏览器的requestIdleCallbackApi实现,新建index.js并在index.html中引入

    • index.js,这个功能整个就叫做任务调度器
let taskId = 1
function workLoop (deadline) {
  taskId ++
  console.log(deadline.timeRemaining())
  let shouldYield = false
  while (!shouldYield) {
    // 之后把渲染任务放到这里来执行
    console.log(`runt task ${taskId}`)
    shouldYield = deadline.timeRemaining() < 1
  }
  requestIdleCallback(workLoop)
}
requestIdleCallback(workLoop)

剩余问题: 之前是一口气把一整个dom树渲染出来

  • 如何把渲染把它分配到每一个任务控制渲染,我们将在后续小节中实现