React调度的原理是什么

这篇文章主要介绍“React调度的原理是什么”,在日常操作中,相信很多人在React调度的原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”React调度的原理是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

异步调度

问题:由于对于大型的 React 应用,会存在一次更新,递归遍历大量的虚拟 DOM ,造成占用 js 线程,使得浏览器没有时间去做一些动画效果,伴随项目越来越大,项目会越来越卡。

对比Vue:

Vue 有这 template 模版收集依赖的过程,轻松构建响应式,使得在一次更新中,Vue 能够迅速响应,找到需要更新的范围,然后以组件粒度更新组件,渲染视图。

React 中,一次更新 React 无法知道此次更新的波及范围,所以 React 选择从根节点开始 diff ,查找不同,更新这些不同。

解决:

把 React 的更新,交给浏览器自己控制,浏览器先执行绘制任务,空闲时间执行更新任务,解决了卡顿问题。即采用异步调度的方法。

时间分片

React让浏览器控制React更新:浏览器每执行一次事件循环都会:处理事件,执行 js,调用requestAnimation,布局 Layout,绘制 Paint,在一次执行后,浏览器进入空闲时,可以执行更新任务

谷歌浏览器提供的一个 API, 在浏览器有空余的时间,浏览器就会调用 requestIdleCallback 的回调。

requestIdleCallback(callback,{ timeout })

  • callback 回调。浏览器空余时间执行回调函数。

  • timeout 超时时间。如果浏览器长时间没有空闲,那么回调就不会执行,为了解决这个问题,可以通过 requestIdleCallback 的第二个参数指定一个超时时间。

React 为了防止 requestIdleCallback 中的任务由于浏览器没有空闲时间而卡死,所以设置了 5 个优先级。

  • Immediate -1 需要立刻执行。

  • UserBlocking 250ms 超时时间250ms,一般指的是用户交互。

  • Normal 5000ms 超时时间5s,不需要直观立即变化的任务,比如网络请求。

  • Low 10000ms 超时时间10s,肯定要执行的任务,但是可以放在最后处理。

  • Idle 一些没有必要的任务,可能不会执行。

模拟requestdleCallback

条件:

  • 可以主动让出主线程,让浏览器去渲染视图。

  • 一次事件循环只执行一次,因为执行一个以后,还会请求下一次的时间片。

宏任务:在下次事件循环中执行,不会阻塞浏览器更新。且浏览器一次只会执行一个宏任务。

1、采用setTimeout(fn, 0),间隔时间会变成 4 毫秒左右,不是最优选方案

2、采用MessageChannel 接口,允许开发者创建一个新的消息通道,并通过它的两个 MessagePort 属性发送数据。

React调度的原理是什么  react 第1张

在一次更新中,向浏览器请求执行更新任务,调用 requesetHostCallbcak,将更新任务 函数callback赋值给 scheduleHostCallback,port2 向 port1 发起 postMessage消息通知。

port1 会通过 onmessage,接受来自 port2 消息,执行更新任务 scheduleHostCallback,执行完后,清空任务。

异步调度原理

React 发生一次更新,会统一走 ensureRootIsScheduled(调度应用)

对于 正常更新 会走 performSyncWorkOnRoot 逻辑,最后会走 workLoopSync

React调度的原理是什么  react 第2张

对于 低优先级的异步更新 会走 performConcurrentWorkOnRoot 逻辑,最后会走 workLoopConcurrent

React调度的原理是什么  react 第3张

区别:异步模式会调用一个 shouldYield(),如果当前浏览器没有空余时间, shouldYield 会中止循环,直到浏览器有空闲时间后再继续遍历,从而达到终止渲染的目的。解决了一次性遍历大量的 fiber ,导致浏览器没有时间执行一些渲染任务,导致了页面卡顿。

1、scheduleCallback

更新任务、异步更新任务都是由调度器 scheduleCallback 统一调度的

正常更新任务:

scheduleCallback(Immediate,workLoopSync)

异步更新任务:

/* 计算超时等级,就是如上那五个等级 */
var priorityLevel = inferPriorityFromExpirationTime(currentTime, expirationTime);
scheduleCallback(priorityLevel,workLoopConcurrent)

scheduleCallback() 函数执行过程

React调度的原理是什么  react 第4张

scheduleCallback 流程如下:

  • 创建一个新的任务 newTask。

  • 通过任务的开始时间( startTime ) 和 当前时间( currentTime ) 比较:当 startTime > currentTime, 说明未过期,存到 timerQueue,当 startTime <= currentTime,说明已过期, 存到 taskQueue。

  • 如果任务没有过期,用 requestHostTimeout 延时执行 handleTimeout

  • 如果任务过期,并且没有调度中的任务,那么调度 requestHostCallback

  • 本质上调度的是 flushWork

2、requestHostTimeout

通过 setTimeout 来进行延时指定时间的。

React调度的原理是什么  react 第5张

延时执行 handleTimeoutcancelHostTimeout 用于清除当前的延时器。

3、handleTimeout

延时时间后,handleTimeout 会把任务重新放在 requestHostCallback 调度。

React调度的原理是什么  react 第6张

通过 advanceTimers 将 timerQueue 中过期的任务转移到 taskQueue 中。然后调用 requestHostCallback 调度过期的任务。

4、advanceTimers

React调度的原理是什么  react 第7张

如果任务已经过期,那么将 timerQueue 中的过期任务,放入 taskQueue。

5、flushWork

requestHostCallback ,放入 MessageChannel 中的回调函数是flushWork。

React调度的原理是什么  react 第8张

flushWork 如果有延时任务执行的话,那么会先暂停延时任务,然后调用 workLoop ,去真正执行超时的更新任务。

6、workLoop

workLoop 是调度中的 workLoop

React 的更新任务最后都是放在 taskQueue 中

React调度的原理是什么  react 第9张

workLoop 会依次更新过期任务队列中的任务

调度流程图

React调度的原理是什么  react 第10张

到此,关于“React调度的原理是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注蜗牛博客网站,小编会继续努力为大家带来更多实用的文章!

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

评论

有免费节点资源,我们会通知你!加入纸飞机订阅群

×
天气预报查看日历分享网页手机扫码留言评论Telegram