React同步与异步的更新模式
在React中有两种更新的模式 分别为同步更新和异步更新
同步模式
同步模式是 React 的 "传统" 渲染模式。在同步模式中,React 在更新 DOM 时会一次完成所有操作,直到整个更新过程完成。由于 JavaScript 是单线程的,当 React 通过这种方式进行组件更新时,它会阻塞浏览器的其他任务,如页面渲染、用户输入、动画、加载资源等。
同步模式的问题是,在非常复杂的组件树或频繁状态更新的情况下,用户可能会注意到短暂的卡顿,因为所有任务都是顺序执行的,没有充分利用浏览器的客观渲染能力。
function workLoopSync() {
debugger
// Already timed out, so perform work without checking if we need to yield.
while (workInProgress !== null) {
performUnitOfWork(workInProgress);
}
}
并发模式
并发模式是 React 18 引入的新特性,目的是提高用户体验。在并发模式中,React 充分利用了 JavaScript 的异步特性,允许浏览器在执行 React 组件更新的过程中进行其他操作。这种方式可以减少阻塞,避免出现卡顿现象。
React 通过切断任务执行(分片调度),让浏览器有时间处理其他高优先级任务(如用户输入、加载资源),实现并发模式。这种方式可以提高响应性,尤其是在大型应用程序中表现得更加突出。
并发模式的核心优势:
- 优先级:React 可以识别高优先级或低优先级的更新任务,为不同任务分配不同的处理时间。高优先级任务会更快进行处理,如用户输入事件。
- 预渲染:React 可以在后台预先渲染未显示的内容,当用户需要查看该内容时,可以更快地显示新内容。
- 延迟渲染:React 可以跳过长时间非必要渲染,减少用户感知到的卡顿和重绘。
function workLoopConcurrent() {
// Perform work until Scheduler asks us to yield
while (workInProgress !== null && !shouldYield()) {
performUnitOfWork(workInProgress);
}
}在调试栏中查看并发
yield做了什么事
通过源代码我们发现同步更新与并发更新的差异只是并发更新中多了一个shouldYield shouldYield到底做了些什么,我们来看一下源代码
var frameYieldMs = 5;
var frameInterval = frameYieldMs;
function shouldYieldToHost() {
var timeElapsed = getCurrentTime() - startTime;
if (timeElapsed < frameInterval) {
// The main thread has only been blocked for a really short amount of time;
// smaller than a single frame. Don't yield yet.
return false;
} // The main thread has been blocked for a non-negligible amount of time. We
return true;
}
我们发现在默认的并发情况情况下,React每帧有5ms的时间更新Fiber,如果Fiber仍然没有执行完成,则放权执行其他任务(浏览器或者其他js任务)