时间分片,将一个耗时任务碎片化,每一块完成后去执行一次别的任务(由 React 负责协调),避免主线程被占据,使得其他线程能够正常运行,保持页面的响应。如果在完成一个时间片后发生了高优先级的任务,就会打断当前进行的(比如一个任务进行了 1/2 后交还控制权了,突然来了个高优先级任务,等这个高优先级任务完成,原本执行了一半的那个任务又要重新执行,是的,完全作废,等下一次再重头来过)。这种机制看起来很奇怪但也不,因为 Fiber 实际上一次更新过程分成两个阶段,reconciliation 协调阶段和 commit 提交阶段,第一阶段 fiber 会确认需要被更新的 DOM,此时是可以被打断的,第二阶段 commit 过程则不会被打断,直接把 DOM 更新完。

第一阶段的 life cycle func

  • componentWillMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate

第二阶段的

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

不可中断,因为我们需要确保各种副作用 IO 正常执行。

注意那些你想要让其只触发一次的函数,不要把副作用放在 willMount 和 willUpdate 里

Fiber 做了什么?自己的协调过程可中断以后,就意味着 React 不会霸占着 CPU 不让出,这样浏览器就有了更多时间响应用户(页面持续响应,用户就感觉不到更新了)。司徒正美老师也提到,给了浏览器喘息之机,它可以对代码进行编译时优化,修正 reflow。

Concurrent 并发与 Parallelism 并行,前者是在同时处理许多事情,后者则是同时做许多事情

单处理器进程调度策略

  • 先到先得,先来的先执行,然后下一个。
    • 对短进程不利,执行时间不长但可能等待时间长。
    • 对 IO 进程不利,每次在 CPU 与 IO 之间切换都需要重新排队
  • 轮转,每个进程拥有相同的执行时间,某个进程消耗完时间后,抢占执行权或等待其执行完毕后获得执行权(非抢占)
  • 最短优先,短进程最先执行。
  • 最短剩余时间
  • 最高响应比优先 响应比 = (等待执行时间 + 进程执行时间) / 进程执行时间,短进程会被优先执行,长进程随着等待时间变长优先级会变高。

Vue 选择优化每次渲染计算,尽可能缩短执行时间。React 选择快速的响应用户,让用户体验更流畅。

浏览器中没有抢占/中断/恢复的机制,只能由 React 主动让出,即合作式调度,浏览器通过 requestIdleCallback(浏览器在有空的时候执行我们的回调函数,回调中会有一个 ddl,我们最好在这个浏览器提供的时间片内把事情干完。)分配时间片,在这个时间内执行完毕后交还控制权。

React 实现了一个类似 rIC 的机制,并制定了任务优先级(Immediate -> UserBolcking -> Normal -> Low -> Idle)

每一个纤程(或者说最小执行单元)执行完毕后,React 会检查剩余时间,如果不够了就会不管后面的任务,先直接交还控制权。如果时间还够,就会执行下一个执行单元。