「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」。
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方法值得我们学习,去处理项目第三方包过多的问题。
感谢阅读,欢迎动动你的小手,给个赞吧。