React调度机制之scheduleWork深度剖析(下)
2024-01-06 01:22:27
中断正在执行的任务
在React中,当一个高优先级的任务到来时,当前正在执行的任务可以被中断,以便优先执行高优先级的任务。这是通过scheduleCallbackForRoot()
函数来实现的。
function scheduleCallbackForRoot(root, callback, expirationTime) {
const updateExpirationTime = root.updateExpirationTime;
if (expirationTime > updateExpirationTime) {
root.updateExpirationTime = expirationTime;
// ...
if (isRendering) {
// ...
return;
}
// ...
}
}
当一个高优先级的任务到来时,scheduleCallbackForRoot()
函数首先会检查当前的updateExpirationTime
是否小于高优先级任务的expirationTime
。如果updateExpirationTime
小于expirationTime
,则将updateExpirationTime
更新为expirationTime
,并中断当前正在执行的任务。
中断当前任务后,scheduleCallbackForRoot()
函数会将高优先级任务添加到任务队列中,等待调度。当调度器下次执行时,会优先执行高优先级任务。
继续中断的任务
在中断当前任务后,React会将中断的任务添加到任务队列中,等待调度。当调度器下次执行时,会继续执行中断的任务。
function continueWork(current, workInProgress, renderExpirationTime) {
// ...
if (workInProgress.expirationTime > renderExpirationTime) {
// ...
// 中断当前任务
return;
}
// ...
}
当调度器继续执行中断的任务时,会首先检查任务的expirationTime
是否大于当前的renderExpirationTime
。如果expirationTime
大于renderExpirationTime
,则任务需要被中断,以便优先执行其他任务。否则,任务可以继续执行。
React16之前的setState()和React Fiber中的setState()的区别
在React16之前,当调用setState()
时,React会将update
添加到update队列
中,然后等待update队列
中的所有update
都调度完后,才会执行render()
函数。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
this.setState({ count: 1 });
this.setState({ count: 2 });
this.setState({ count: 3 });
}
render() {
return (
<div>
{this.state.count}
</div>
);
}
}
在上面的例子中,当调用componentDidMount()
时,会依次调用三次setState()
,将count
的状态更新为1、2、3。但是,在React16之前,这些update
都会被添加到update队列
中,而不会立即执行。只有当update队列
中的所有update
都调度完后,才会执行render()
函数,并将count
的状态更新为3。
在React Fiber中,当调用setState()
时,React会将update
添加到update队列
中,但是不会等待update队列
中的所有update
都调度完后,才会执行render()
函数。相反,React Fiber会立即执行update队列
中的第一个update
,然后将剩余的update
添加到update队列
中,等待下次调度。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
this.setState({ count: 1 });
this.setState({ count: 2 });
this.setState({ count: 3 });
}
render() {
return (
<div>
{this.state.count}
</div>
);
}
}
在上面的例子中,当调用componentDidMount()
时,会依次调用三次setState()
,将count
的状态更新为1、2、3。在React Fiber中,这些update
都会被添加到update队列
中,但是不会等待update队列
中的所有update
都调度完后,才会执行render()
函数。相反,React Fiber会立即执行update队列
中的第一个update
,并将count
的状态更新为1。然后,React Fiber会将剩余的两个update
添加到update队列
中,等待下次调度。
总结
在本文中,我们讨论了React调度机制中的scheduleWork()
函数。我们了解了如何中断正在执行的任务,优先执行优先级比当前高的任务,以及如何在中断后继续之前的任务。此外,我们还比较了React16之前的setState()
和React Fiber中的setState()
的区别。