成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

React內部是如何實現(xiàn)Cache方法的?

開發(fā) 前端
React組件經常render,如果在id不變的情況下,由于User組件render導致不斷發(fā)起請求,顯然是不合理的。這種情況下就需要cache方法。當id不變時,即使User組件反復render,fetch(id)都返回同一個值。本文來聊聊cache的源碼實現(xiàn)。

大家好,我卡頌。

前幾天寫的一篇介紹use這個新hook的文章中聊到React原生實現(xiàn)了一個緩存函數的方法 —— cache。

對于如下代碼,被cache包裹的函數,當多次調用時,如果傳參不變,會始終返回緩存值:

const cacheFn = cache(fn);
cacheFn(1, 2, 3);
// 不會執(zhí)行fn,直接返回緩存值
cacheFn(1, 2, 3);

React內為什么需要cache方法呢?考慮如下組件:

const fetch = cache(fetchUserData);

function User({id}) {
const {name} = use(fetch(id));

return <p>{name}</p>;
}

User組件會根據用戶id請求用戶數據,并渲染用戶名。

如果id改變,那么fetch方法重新發(fā)起請求是正常邏輯。

但是,React組件經常render,如果在id不變的情況下,由于User組件render導致不斷發(fā)起請求,顯然是不合理的。

所以,這種情況下就需要cache方法。當id不變時,即使User組件反復render,fetch(id)都返回同一個值。

本文來聊聊cache的源碼實現(xiàn)。

分析實現(xiàn)思路

整個方法實現(xiàn)一共有64行代碼,首先我們來分析下實現(xiàn)要點。

如果參數不變,則使用緩存的值。這意味著我們需要處理:

參數的順序

舉個例子,當參數順序變了,不使用緩存值:

const cacheFn = cache(fn);
cacheFn(1, 2, 3);
// 不使用緩存值
cacheFn(3, 2, 1);

區(qū)別處理引用類型、原始類型參數

舉個例子,當同一位置的參數傳遞了同一個引用類型值,則返回緩存值:

const cacheFn = cache(fn);
const obj = {};
cacheFn(1, obj, 3);
// 返回緩存值
cacheFn(1, obj, 3);

當同一位置的參數傳遞了不同引用類型值,則不返回緩存值:

const cacheFn = cache(fn);
const obj = {};
cacheFn(1, obj, 3);
// 不返回緩存值
cacheFn(1, {}, 3);

緩存的垃圾回收

緩存數據時,要注意「緩存失效但是引用的數據沒有釋放」造成的內存泄漏問題。

所以,對于引用類型數據,可以使用WeakMap保存。

對于原始類型數據,可以使用Map保存。

WeakMap與Map的區(qū)別在于 —— 在WeakMap中,key到他對應的value是弱引用。這意味著當沒有其他數據引用這個key時,他可以被垃圾回收。而在Map中,key到value是強引用,即使沒有其他數據引用這個key,他也不會被垃圾回收。

實現(xiàn)原理

本文不會介紹具體的代碼實現(xiàn)(大段貼代碼讓人看起來頭疼)。

我會用示例圖講解實現(xiàn)原理。了解原理后,如果你對實現(xiàn)細節(jié)感興趣,可以參考:

  • cache的源碼實現(xiàn)PR[1]
  • cache的在線示例[2]

對于如下代碼:

const cacheFn = cache(fn);
const obj = {};
cacheFn(1, obj, 3);

cacheFn的每個傳參,對應cache內部的一個cacheNode節(jié)點:

// CacheNode構造函數
function createCacheNode<T>(): CacheNode<T> {
return {
s: UNTERMINATED,
v: undefined,
o: null,
p: null
};
}

字段的意義如下:

  • s:cacheNode的緩存狀態(tài),有 未中止/中止/發(fā)生錯誤 3種狀態(tài)。
  • v:cacheNode緩存的值。
  • o:緩存的引用類型值。
  • p:緩存的原始類型值。

上述cacheFn執(zhí)行后會生成如下cacheNode鏈式結構:

圖片

讓我們看看這個鏈式結構如何解決文章開篇提到的3個問題。

如何解決參數的順序?

可以看到,上圖中最后一個cacheNode節(jié)點的狀態(tài)(cacheNode.s)為「中止」。

如果后續(xù)執(zhí)行cacheFn傳入相同的參數,則會復用緩存的cacheNode節(jié)點。

如果所有傳參都相同,那么會復用完整的cacheNode鏈,此時最后一個cacheNode節(jié)點為「中止」狀態(tài),則不需要重新執(zhí)行cacheFn方法計算返回值,而是直接返回緩存的值(cacheNode.v)。

如果后續(xù)執(zhí)行cacheFn,傳入新的參數,則前后的cacheNode鏈不會一致。

比如:

// 第一次
cacheFn(1, obj, 3);
// 第二次
cacheFn(1, 3, obj);

則第二次生成的cacheNode鏈中,第二個節(jié)點就與之前不同(之前obj,之后3),則后續(xù)cacheNode節(jié)點也不會相同。

圖片

通過這種鏈式結構,保證了只有當所有參數保持一致,才能返回緩存的值。否則將重新執(zhí)行函數,并緩存新的返回值與cacheNode鏈。

如何處理引用類型值

可以從圖中發(fā)現(xiàn),對于引用類型參數(比如示例中的obj),對應一個weakMap節(jié)點。

這不僅意味著當沒有其他數據引用他時,這個cacheNode節(jié)點能夠釋放內存,同時也意味著這個cacheNode之后的cacheNode鏈會斷掉,他們占用的內存也會釋放。

而原始類型值不存在這樣的問題,從圖中可以發(fā)現(xiàn),原始類型值對應一個map節(jié)點。

總結

cache方法是React內部實現(xiàn),未來會暴露給開發(fā)者使用的緩存方法,可以緩存任意函數。

當多次執(zhí)行并傳遞相同的參數給cache包裹的函數時,后續(xù)執(zhí)行會返回緩存的值。

這是為了應對「某些函數需要在React組件多次render間返回穩(wěn)定的值」的場景。

比如:對于相同的傳參,請求數據的函數返回同一個promise。

cache的實現(xiàn)方式是 —— 基于傳參,構造一條cacheNode鏈,傳參的穩(wěn)定對應了鏈表的穩(wěn)定,并最終對應了返回值的穩(wěn)定。

參考資料

[1]cache的源碼實現(xiàn)PR:https://github.com/sebmarkbage/react/blob/ecdf734d1aa73d9f5f09f5a8e7fa5685f5f1bd29/packages/react/src/ReactCache.js。

[2]cache的在線示例:https://codesandbox.io/s/amazing-leaf-viq4q7?file=/src/cache.js。

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2021-08-19 16:56:37

Python內存開發(fā)

2020-02-12 15:08:41

KVM內部運作

2023-11-23 19:30:35

Python編程語言

2022-08-22 16:23:11

React特性

2023-10-07 08:41:42

JavaJVM

2022-04-14 09:01:39

React源碼Flow

2023-05-05 18:38:33

多級緩存Caffeine開發(fā)

2023-04-06 09:41:00

React 組件重渲染

2022-12-23 08:34:30

HookReact

2022-07-27 07:32:28

Debug版本arthas

2019-10-08 11:10:18

React自動保存前端

2022-05-15 22:08:58

ReactHookdebounce

2024-11-05 15:02:41

2022-03-11 10:23:02

React性能優(yōu)化

2020-10-21 08:38:47

React源碼

2021-09-17 12:50:10

MySQL數據庫ACID

2023-05-31 07:29:46

2023-12-05 15:58:06

React開發(fā)

2022-05-16 08:22:37

零拷貝Netty

2022-12-07 11:21:30

Reactdiff
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲高清在线 | 久久久久国产一区二区三区不卡 | 国产精品1区2区3区 国产在线观看一区 | 日本三级在线网站 | 特黄视频| 欧美日韩精品免费 | 青青久久 | 国产精品永久免费视频 | 精品一区精品二区 | 亚洲一区综合 | 玖操| 久久精品无码一区二区三区 | 成人性生交大片免费看中文带字幕 | 中文字幕在线观看第一页 | 国产免费xxx | 亚洲国产一区在线 | 国产二区视频 | 天天操网 | 久久精品一区 | 中文字幕免费观看 | 久久久91精品国产一区二区三区 | 免费黄色片在线观看 | 日韩不卡视频在线观看 | 久久777 | 狠狠婷婷综合久久久久久妖精 | 亚洲视频在线一区 | 成人免费黄色 | 国产高清视频在线观看播放 | 欧美一区二区三 | 国产精品久久久久久久久久三级 | 欧美黄色片 | 在线观看亚洲专区 | 最近中文字幕在线视频1 | 91欧美精品成人综合在线观看 | 精品久久国产 | 超碰最新在线 | 宅男噜噜噜66一区二区 | 粉嫩一区二区三区四区公司1 | 99riav国产一区二区三区 | 狠狠综合久久av一区二区小说 | 久久亚洲国产精品日日av夜夜 |