-
-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React Fiber架构解析(一) #55
Labels
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
前言
最近在学习React Fiber架构,把相关内容整理了下,方便理解并且加深自己的印象。本篇文章主要分为三个内容:基础知识储备,架构的设计,框架运行流程。
1.单线程和“非阻塞”
单线程:js 是单线程的,这意味着在任何给定时间,只能执行一段代码。所有的代码执行都在一个主线程上完成。这种设计简化了编程模型,因为开发者不需要处理多线程编程中常见的数据竞争、死锁等问题
非阻塞:尽管 js 是单线程的,但它使用了事件循环和回调机制来支持非阻塞的 I/O 操作(例如网络请求、文件操作等)。这意味着当一个 I/O js 不会停下来等待操作完成,而是继续执行后续的代码。当 I/O 操作完成后,对应的回调函数会被放入事件队列中,等待主线程执行。
2.浏览器的刷新频率
因为JS 脚本执行和浏览器布局、绘制不能同时执行,所以 gui渲染线程 与 js线程 是互斥的。主流浏览器刷新频率为 60Hz,即每(1000ms / 60Hz)16.6ms 浏览器刷新一次。在 16.6ms 内,浏览器要处理js脚本执行、 样式布局、 样式绘制,如果任一环节的执行时间超过了16.6ms就会导致页面掉帧、卡顿。
人眼的可视帧数是24Hz,如果低于这个帧数,就能明显感受到卡顿,越高于这个帧数显示就越流畅。
3.单核cpu运行多任务
当我一次了解React Fiber架构时第一时间想到的是单核cpu时代,计算机是如何保证“多任务”运行的。
3.1 .时间片轮转调度
3.2 中断机制
3.3 多级反馈队列
单核 cpu 和js 单线程的模型很像,都是一次只能处理一个任务,但是单核cpu借助 时间片调度、中断机制、多级反馈队列模拟了运行多任务目的。
4.基础API依赖
react主要是用下面的浏览器api ,在浏览器模拟“多任务”的执行。
4.1 requestIdleCallback
这个函数将在浏览器空闲时期被调用。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序
4.2 requestAnimationFrame
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
为了提高性能和电池寿命,在大多数浏览器里,当
requestAnimationFrame()
运行在后台标签页或者隐藏的 <iframe> 里时,requestAnimationFrame()
会被暂停调用以提升性能和电池寿命。4.3 MessageChannel
使用
MessageChannel()
构造函数来创建通讯信道。一旦创建,信道的两个端口即可通过MessageChannel.port1
和MessageChannel.port2
属性进行访问(都会返回 MessagePort 对象)。创建信道的应用程序使用 port1,在另一端的程序使用 port2——你向 port2 发送信息,然后携带 2 个参数(需要传递的消息,要传递所有权的对象,在这里是 port 自身)调用 window.postMessage 方法将端口信息传递到另一个浏览器上下文。4.4 MessageChannel的执行时机
在浏览器环境中调整上述代码中的顺序,看下面的执行结果:
对比上图代码在浏览器环境中执行结果得出以下结论:
new Promise()函数,是在主线程立即执行;
MessageChannel和setTimeout(fn, 0)类似,主线程执行结束后,如果有postMessage,立即执行。并且两者之前没有优先级关系,谁在前面就先执行谁
微任务then的执行优先级比MessageChannel和setTimeout(fn, 0)都要高;
浏览器兼容性
因为浏览器兼容性问题,react主要使用requestAnimationFrame和MessageChannel 来模拟实现requestIdleCallback的功能,并且是用settimeout来实现降级策略。
5.如何模拟“闲时”调用
根据前置知识,**requestAnimationFrame(RAF)**可以在浏览器重绘前执行指定的回调函数。可以将优先级较高(显示、用户操作等)相关的任务用RAF回调执行,当一帧执行完之后如果还有剩余的空闲时间,就通过postmessage告知任务队列当前帧有空余时间可以执行低优先级的任务。
6.扩展知识
进程
进程是操作系统分配资源和调度的基本单位。一个进程包含了运行程序所需的代码和数据资源,以及执行的上下文。进程间相互独立,拥有各自独立的地址空间,一个进程无法直接访问另一个进程的资源和数据。
线程
线程是进程内的一个执行流程,是 CPU 调度和执行的最小单位。一个进程可以包含多个线程,它们共享该进程的资源(如内存空间)。线程之间的通信和数据共享比进程间更简单、效率更高,但这也意味着线程之间的同步非常重要,以避免数据竞争和不一致。协程
协程
协程是一种用户态的轻量级"线程",它的调度完全由用户控制,不需要操作系统介入。协程提供了非常高效的异步编程模型,能在等待操作(如 I/O)完成时挂起当前协程,并恢复其他协程的执行,从而提高程序的整体效率和响应性。
纤程
纤程是一种比线程更轻量级的协作单元,它与协程类似,通常用于特定的程序库中实现。纤程的调度也是用户级的,允许开发者控制何时进行任务切换,适用于需要高度控制并发操作的场景。
The text was updated successfully, but these errors were encountered: