react源码解读之ReactLazy.js
Wakeable,Thenable傻傻分不清楚
import type {Wakeable, Thenable} from 'shared/ReactTypes'; export interface Wakeable { then(onFulfill: () => mixed, onReject: () => mixed): void | Wakeable; } export interface Thenable<+R> { then<U>( onFulfill: (value: R) => void | Thenable<U> | U, onReject: (error: mixed) => void | Thenable<U> | U, ): void | Thenable<U>; } import {REACT_LAZY_TYPE} from 'shared/ReactSymbols'; REACT_LAZY_TYPE = symbolFor('react.lazy'); 复制代码
Wakeable
,可唤醒的。这样一个接口规定实现它的类,必须实现一个then
方法,这个then
方法的返回值类型为void
(空)或者Wakeable
。它接收两个函数参数,成功时的回调和失败时的回调。Thenable
接口的定义与Wakeable
的定义类似,只是函数参数的入参不一样,Thenable
的onFulfill
方法的返回值可以为Thenable
,也就是说可以无限地往下then
下去。REACT_LAZY_TYPE
标识符标识了react
的懒加载类型,读完源码你会知道react
懒加载类型有何作用。
如果这里不太明白,建议继续往下看,山穷水复疑无路,柳暗花明又一村,不要在这颗树上吊死了。
问题Wakeable与Thenable有何不一样?
Thenable的状态值
const Uninitialized = -1; const Pending = 0; const Resolved = 1; const Rejected = 2; 复制代码
Uninitialized,表示未初始化,值为-1。
Pending,表示正在加载中,值为0。
Resolved,表示已经加载完成并且加载成功,值为1。
Rejected,表示已经加载完成但是加载失败,值为2。
真的值得吗?
payload表示有效载荷,关键信息 假设Thenable方法会返回一个未知量,那么这个未知量代表什么呢? 请阅读下面的代码:
type UninitializedPayload<T> = { _status: -1, _result: () => Thenable<{default: T, ...}>, }; type PendingPayload = { _status: 0, _result: Wakeable, }; type ResolvedPayload<T> = { _status: 1, _result: {default: T}, }; type RejectedPayload = { _status: 2, _result: mixed, }; 复制代码
根据状态值,将有效载荷分为4种类型。
UninitializedPayload
,未初始化的有效载荷,_result属性为一个函数返回一个Thenable。PendingPayload,加载中的有效载荷,_result属性为一个Wakeable.
ResolvedPayload,已完成的有效载荷,_result属性为一个对象,默认值为泛型T对应的数据类型。
RejectedPayload,已失败的有效载荷,—result属性为mixed,表示任意类型。
可以看到,在Resolved阶段,返回的是任意数据类型(mixed),这个mixed又由Wakeable返回,也就是加载中有效载荷的_result属性执行后返回。未初始化的有效载荷的_result属性调用后,返回一个Thenable,这个Thenable会返回一个Wakeable,也就是将会返回实际数据的一个函数。ResolvedPayload就是我们实际所需要的数据。
爆炸,就简简单单的一个异步调用返回数据的功能,被设计成了四层。这真的值得吗?
ctor是个什么der
export function lazy(ctor) { const payload = { _status: Uninitialized, _result: ctor, }; const lazyType = { $$typeof: REACT_LAZY_TYPE, _payload: payload, _init: lazyInitializer, }; return lazyType; } 复制代码
最后,react导出了一个lazy函数,万事大吉。
ctor是个什么der?
首先,我们看看React.lazy这个api的使用。
const LazyComponent = React.lazy(() => import('../componets/LazyComponent)); 复制代码
可以看到,ctor是一个函数,这个函数返回一个Thenable的异步调用。
function resolveLazy(lazyType) { const payload = lazyType._payload; const init = lazyType._init; return init(payload); } function lazyInitializer(payload) { if (payload._status === Uninitialized) { const ctor = payload._result; const thenable = ctor(); thenable.then() ... } 复制代码
resolveLazy方法会调用lazyInitializer的_init方法,最开始,会进入未初始化的状态判断。 调用ctor得到一个thenable的对象。在异步调用过程中,payload的状态将是Pending。 调用结束之后会返回moduleObject.default,返回这个组件渲染所必须的payload。
异步路由不够,第三方包也要异步。
在一个项目的迭代过程中,随着模块的越来越多,webpack打包的第三方包将会越来越多,这样导致系统首次加载将会越来越慢。虽然有了异步路由的加持,但是在main.js文件里加入过多的文件,项目大到一定程度,仍将导致主入口文件的体积过大。React的lazy方法值得我们学习,去处理项目第三方包过多的问题。
感谢阅读,欢迎动动你的小手,给个赞吧。
伪原创工具 SEO网站优化 https://www.237it.com/
作者:cutekio
链接:https://juejin.cn/post/7035996414874222623