react 缓存
一、作用
二、缓存
备注
ReactSharedInternals()由 ReactSharedInternals 实现
// export function cache<A: Iterable<mixed>, T>(fn: (...A) => T): (...A) => T {
export function cache<A extends Iterable<mixed>, T>(
fn: (...a: A) => T,
): (...a: A) => T {
return function () {
const dispatcher = ReactSharedInternals.A;
if (!dispatcher) {
// If there is no dispatcher, then we treat this as not being cached.
// 如果没有调度器,那么我们将其视为未缓存。
return fn.apply(null, arguments);
}
const fnMap: WeakMap<any, CacheNode<T>> = dispatcher.getCacheForType(
createCacheRoot,
);
const fnNode = fnMap.get(fn);
let cacheNode: CacheNode<T>;
if (fnNode === undefined) {
cacheNode = createCacheNode();
fnMap.set(fn, cacheNode);
} else {
cacheNode = fnNode;
}
for (let i = 0, l = arguments.length; i < l; i++) {
const arg = arguments[i];
if (
typeof arg === 'function' ||
(typeof arg === 'object' && arg !== null)
) {
// Objects go into a WeakMap
// 对象存放在 WeakMap 中
let objectCache = cacheNode.o;
if (objectCache === null) {
cacheNode.o = objectCache = new WeakMap();
}
const objectNode = objectCache.get(arg);
if (objectNode === undefined) {
cacheNode = createCacheNode();
objectCache.set(arg, cacheNode);
} else {
cacheNode = objectNode;
}
} else {
// Primitives go into a regular Map
// 原始类型会存入普通 Map
let primitiveCache = cacheNode.p;
if (primitiveCache === null) {
cacheNode.p = primitiveCache = new Map();
}
const primitiveNode = primitiveCache.get(arg);
if (primitiveNode === undefined) {
cacheNode = createCacheNode();
primitiveCache.set(arg, cacheNode);
} else {
cacheNode = primitiveNode;
}
}
}
if (cacheNode.s === TERMINATED) {
return cacheNode.v;
}
if (cacheNode.s === ERRORED) {
throw cacheNode.v;
}
try {
const result = fn.apply(null, arguments);
const terminatedNode: TerminatedCacheNode<T> = cacheNode as any;
terminatedNode.s = TERMINATED;
terminatedNode.v = result;
return result;
} catch (error) {
// We store the first error that's thrown and rethrow it.
// 我们存储抛出的第一个错误并重新抛出它。
const erroredNode: ErroredCacheNode<T> = cacheNode as any;
erroredNode.s = ERRORED;
erroredNode.v = error;
throw error;
}
};
}
三、缓存信号
备注
ReactSharedInternals()由 ReactSharedInternals 实现
export function cacheSignal(): null | AbortSignal {
const dispatcher = ReactSharedInternals.A;
if (!dispatcher) {
// If there is no dispatcher, then we treat this as not having an AbortSignal
// since in the same context, a cached function will be allowed to be called
// but it won't be cached. So it's neither an infinite AbortSignal nor an
// already resolved one.
//
// 如果没有调度器,那么我们将其视为没有 AbortSignal 因为在相同的上下文中,缓存的函数将被
// 允许调用但它不会被缓存。所以它既不是无限的 AbortSignal,也不是已经解析的 AbortSignal。
return null;
}
return dispatcher.cacheSignal();
}
四、常量
// 未终止
const UNTERMINATED = 0;
// 已终止
const TERMINATED = 1;
// 出错
const ERRORED = 2;
五、工具
1. 构建缓存根
function createCacheRoot<T>(): WeakMap<Function | Object, CacheNode<T>> {
return new WeakMap();
}
2. 构建缓存节点
function createCacheNode<T>(): CacheNode<T> {
return {
// status, represents whether the cached computation returned a value or threw an error
// 状态,表示缓存的计算是返回了一个值还是抛出了一个错误
s: UNTERMINATED,
// value, either the cached result or an error, depending on s
// 值,可能是缓存的结果,也可能是一个错误,取决于 s
v: undefined,
// object cache, a WeakMap where non-primitive arguments are stored
// 对象缓存,一个 WeakMap,用于存储非原始类型的参数
o: null,
// primitive cache, a regular Map where primitive arguments are stored.
// 原始缓存,一个普通的 Map,用于存储原始参数。
p: null,
};
}