【React 之 Schedule 调度机制一】:由来、简易流程与demo实现

115 阅读2分钟

Schedule的由来

首先我们需要知道:React是用Javascript构建快速响应的大型Web应用程序的首选方式,实现的关键就在于"快速响应",那么制约快速响应的因素主要分为以下两种情况:

  1. 电脑菜或者大计算量操作,页面掉帧:市面上大多数设备屏幕刷新率为60次/秒,当每秒绘制的帧数(FPS)达到60时,页面是流畅的,即每帧的预算时间约为16.66ms,在每一帧内,如果浏览器需要执行一个耗时过长的任务,则当前帧不会被绘制,造成掉帧
  2. 进行I/O操作,需要等待数据返回才能接着操作,等待的过程不能快速响应

上述两个问题可概括为CPU瓶颈和I/O瓶颈,为了解决这两个问题,react提出了:

  1. 利用 "Time Slice" 将虚拟 DOM(VDOM)的执行过程切成一个个小宏任务,并为每个宏任务设置一定的耗时(通常为 5ms)。如果某个宏任务执行耗时过长,会自动中断该任务,将渲染控制权交还给浏览器,以确保页面的流畅性。
  2. 将人机交互的研究成果整合到 UI 中,根据用户对不同操作的卡顿感知程度,为不同操作赋予不同的优先级。每个任务按照优先级进行排序,然后根据排序依次执行回调,并且实现了任务中断等功能,以保证高优先级任务能够及时得到处理。

Schedule简易流程

最简易的Scedule调度流程,流程主要分为3步(如下图所示):

  1. 任务插入:用户通过点击按钮调度流程,向workList列队插入work(即用户的操作);
  2. 任务取出与传递:schedule从workList取出work,传递给perform
  3. 任务执行:perform方法执行work,执行完毕后通知schedule
  4. 循环调度:schedule继续调度work传递给perform,周而复始

image.png

Schedule简易demo实现

<template>
   <div @click="setTask">触发Schedule</div>
</template>

<script>
   data() {
    return {
       workList: []
    }
   }
   
   methods: {
      setTask() {
         this.workList.push({count:20});
         this.scedule()
      };
      schedule () {
          const curWork = workList.pop();
          if(curWork) {
             perform(curWork)
          }
      };
      
      perform(curWork) {
         while(curWork.count) {
            curWork.count--;
            console.log("执行任务")
         }
         schedule()
      }
   }
</script>
上述代码中,用户点击触发了setTask事件,setTask向workList插入了一个任务,该任务中需要执行20遍打印操作,即代码执行完毕后,F12控制台显示20个"执行任务"文案,那么一个小的schedule模块demo就实现了,下一篇讲优先级,并结合优先级对代码进行扩展改造