精读React核心概念(1) --React Fiber
前言
最近为了深化自己React核心概念的学习,在掘金上认真学习荒山大佬的文章,个人感觉主要有两部分,一部分是每年的React Conf推出的新的核心特性的深入理解,一种是React的开发规范和设计原则。个人学习过程中感觉到受益匪浅,因此在这里根据自己的学习总结一下,肯定没有荒山讲得好,大家可以通过这个链接去看荒山大佬的文章,当然如果你想简单的了解一下的话,我的文章会更简单点.
单处理进程调度
在讲Fiber之前,为了更好的理解,先讲一下单处理进程的几个调度方法。
首先是先到先得的方法,也可以认为没有方法,谁先来处理谁,这样做的坏处显而易见,对于一些短时间进程,他们前面如果有很长时间的进程在处理,就会很耽误他们自己的处理时间,因为如果先处理他们的话会很快的处理完;同时也对IO密集型任务不利,他们阻塞休眠后又会重新回到候选队列。
接着是时钟轮转的调度方法,设定一个时间段,每过这个时间段或者阻塞休眠时就会先放下,去处理其他的进程。这样做法有个问题就是时间段的大小不好确定,设定长了其实和
第一种方法没什么区别,太短的话,线程切换也是耗时的,自然也不好;同时这样的方法也没有解决IO密集型任务的问题。
接着是最短进程优先的方法,顾名思义,这种方法的话属于非抢占型策略,这样操作的缺点也是显而易见,对长进程不利;同时如果长进程进行处理,后面的短进程还是同第一种方法一样迟迟得不到响应。
针对上一种方法的缺点,还有最短剩余时间的方法,新的进程进来后,如果它的执行时间短于正在执行的老进程,那么就会先处理较短的,这样的方式仍然没有解决长进程饥饿的缺陷。
最高响应比优先,主要是针对上面无法处理长进程饥饿的问题提出的,它提供了一个公式来计算相应比:
响应比 = (等待执行时间 + 进程执行时间) / 进程执行时间
这样一定程度上解决了长进程饥饿的问题。
注意上面关于基于最短进程优先的三种方法,它们都是要计算进程处理时间的,这当然也要消耗一部分资源,因此我们提出了一种反馈法,使得他们开始都有同样的优先度,使用抢占策略(诸如时钟轮转)后,他们的优先度就会降低。具体可以唱看荒山大佬的文章,我觉得讲到这里就差不多了。
为什么讲这个
简单地说,JS是单线程的:
它要负责页面的JS解析和执行、绘制、事件处理、静态资源加载和处理, 这些任务可以类比上面’进程‘
相似的,如果有一个“长进程”任务长期霸占CPU,我们也要使用某种调度方法,让用户的体验更加完美,即使扔是只有一个进程在处理,但是给用户的体验是不一样的,就如同我们计算机的进程调度方式一样。
那么Fiber是什么
简单地说,Fiber可以让这种类似CPU密集型的长进程任务变为可中断的任务,通过进程调度可以让浏览器更及时的响应用户的操作。
React 渲染的过程可以被中断,可以将控制权交回浏览器,让位给高优先级的任务,浏览器空闲后再恢复渲染
具体来说,浏览器中其实并没有抢占机制,其实也不存在类似进程的概念,实则是使用了类似协程的控制权让出机制,专业点讲这叫合作式调度,这里浏览器掌握着控制大权,用图表可以如下表示:
那么什么时候浏览器才能判断应该让出控制权了呢,或者说它怎么判断应该处理高优先度任务了呢?
其实他没有办法判断哪些是所谓的高优先级任务,但是它利用了类似requestIdleCallback原理的方法去解决这个问题,通俗的讲,为了优化用户使用浏览器的体验,他会让浏览器在保证运行流畅的前提下,一有空就去回调处理其他事务,同时为了避免任务被饿死,react也做了设置超时时间的设定,使得应该被进行的任务都能被完成。
但是requestIdleCallback这个API目前只有Chrome支持了,所以React自己实现了一个。
同时,尽管这个功能和ES6中generater很像,React也没有直接用,而是使用了Fiber这种方式来替代,具体实现步骤这个荒山大佬的图讲的很清楚:
具体Fiber的实现这里就不讲了,有兴趣可以看原文,同时Fiber是一项非常庞大的任务,可能我们要做的并没有什么,但是潜在里我们程序做的东西已经沧海桑田。