react 最新技术 Time Slicing 和 Suspense !

2,683 阅读3分钟

Time Slicing (时间分片)

React 在渲染(render)的时候,不会阻塞现在的线程 如果你的设备足够快,你会感觉渲染是同步的。如果你设备非常慢,你会感觉还算是灵敏的、 虽然是异步渲染,但是你将会看到完整的渲染,而不是一个组件一行行的渲染出来 同样书写组件的方式

Dan为我们做了一个有趣的Demo:
  • 同步模式下,我们没输入一个字符,React就开始渲染,当React渲染一颗巨大的树的时候,是非常卡的,所以才会有shouldUpdate的出现;
  • Debounced模式简单的来说,就是延迟渲染,比如,当你输入完成以后,再开始渲染所有的变化。这么做的坏处就是,至少不会阻塞用户的输入了,但是依然有非常严重的卡顿
  • 异步渲染模式就是不阻塞当前线程,继续跑。在视频里可以看到所有的输入,表上都会是原谅色的。

简单的来说,react的异步渲染其实就是拉长了render的时间,一次跑一点,所以机器性能很差的,会看到react渲染时有稍微的延迟,但是不是卡顿。

Suspense(/səˈspens/ )悬停(也可以叫做暂停)

  • 在render函数中,我们可以写入一个异步请求,请求数据
  • react会从我们缓存中读取这个缓存
  • 如果有缓存了,直接进行正常的render
  • 如果没有缓存,那么会抛出一个异常,这个异常是一个promise
  • 当这个promise完成后(请求数据完成),react会继续回到原来的render中(实际上是重新执行一遍render),把数据render出来
  • 完全同步写法,没有任何异步callback之类的东西

调用render函数->发现有异步请求->悬停,等待异步请求结果->再渲染展示数据

主要解决:

Suspense主要解决的就是网络IO问题。网络IO问题其实就是我们现在用Redux+saga等等一系列乱七八糟的库来解决的「副作用」问题。react出生到现在都存在的「异步副作用」的问题,而且解决得非常的优雅,使用的是「异步但是同步的写法」,我个人认为,这是最好的解决异步问题的方式。

Suspense的核心功能:同步的方式去书写代码

这个组件就与我们之前书写组件的方式有很大的差异,在react 的 render()函数中,异步去fetch数据是没用的,因为异步函数会在下一个JS事件循环中才会进行,此时,已经渲染完毕了。所以拿到数据了也没用。

  • 引入新的api,可以使得任何state更新暂停,直到条件满足时,再渲染(像async/await)
  • 可以在任何一个组件里放置异步获取数据,而不用做多余的设置
  • 在网速非常快的时候,可设置,整个数据到达Dom,更新完毕以后再渲染。在网速非常慢的时候,可设置,精确到单个组件的等待、以及更新,然后再渲染

使用

const ProfilePage = React.lazy(() => import('./ProfilePage')); // Lazy-loaded

// Show a spinner while the profile is loading
<Suspense fallback={<Spinner />}>
  <ProfilePage />
</Suspense>

react 16给我们带来的一些列重要变化:

  • render/纯组件能够return任何数据结构,以及CreatePortal Api
  • 新的context api,尝试代替一部分redux的职责
  • babel的<>操作符,方便用户返回数组
  • 异步渲染/时间切片(time slicing),成倍提高性能
  • componentDidCatch,错误边界,框架层面上提高用户debug的能力
  • 未来的Suspense,优雅处理异步副作用