IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 从理念到LRU算法实现,起底未来React异步开发方式 -> 正文阅读

[JavaScript知识库]从理念到LRU算法实现,起底未来React异步开发方式

React源码内部在实现不同模块时用到了多种算法与数据机构(比如调度器使用了小顶堆)。

今天要聊的是数据缓存相关的LRU算法。内容包含四方面:

  • 介绍一个React特性
  • 这个特性和LRU算法的关系
  • LRU算法的原理
  • ReactLRU的实现

可以说是从入门到实现都会讲到,所以内容比较多,建议点个赞收藏慢慢食用。

一切的起点:Suspense

React16.6引入了SuspenseReact.lazy,用来分割组件代码。

对于如下代码:

import A from './A';
import B from './B';

function App() {
  return (
    <div>
      <A/>
      <B/>
    </div>
  )
}

经由打包工具打包后生成:

  • chunk.js(包含A、B、App组件代码)

对于首屏渲染,如果B组件不是必需的,可以将其代码分割出去。只需要做如下修改:

// 之前
import B from './B';
// 之后
const B = React.lazy(() => import('./B'));

经由打包工具打包后生成:

  • chunk.js(包含A、App组件代码)
  • b.js(包含B组件代码)

这样,B组件代码会在首屏渲染时以jsonp的形式被请求,请求返回后再渲染。

为了在B请求返回之前显示占位符,需要使用Suspense

// 之前,省略其余代码
return (
  <div>
    <A/>
    <B/>
  </div>
)
// 之后,省略其余代码
return (
  <div>
    <A/>
    <Suspense fallback={<div>loading...</div>}>
      <B/>
    </Suspense>
  </div>
)

B请求返回前会渲染<div>loading.。.</div>作为占位符。

可见,Suspense的作用是:

在异步内容返回前,显示占位符(fallback属性),返回后显示内容

再观察下使用Suspense后组件返回的JSX结构,会发现一个很厉害的细节:

return (
  <div>
    <A/>
    <Suspense fallback={<div>loading...</div>}>
      <B/>
    </Suspense>
  </div>
)

从这段JSX中完全看不出组件B是异步渲染的!

同步和异步的区别在于:

  • 同步:开始 -> 结果
  • 异步:开始 -> 中间态 -> 结果

Suspense可以将包裹在其中的子组件的中间态逻辑收敛到自己身上来处理(即Suspensefallback属性),所以子组件不需要区分同步、异步。

那么,能不能将Suspense的能力从React.lazy(异步请求组件代码)推广到所有异步操作呢?

答案是可以的。

resource的大作为

React仓库是个monorepo,包含多个库(比如reactreact-dom),其中有个和Suspense结合的缓存库 ——?react-cache,让我们看看他的用处。

假设我们有个请求用户数据的方法fetchUser

const fetchUser = (id) => {
  return fetch(`xxx/user/${id}`).then(
    res => res.json()
  )
};

经由react-cachecreateResource方法包裹,他就成为一个resource(资源):

import {unstable_createResource as createResource} from 'react-cache';

const userResource = createResource(fetchUser);

resource配合Suspense就能以同步的方式编写异步请求数据的逻辑:

function User({ userID }) {
  const data = userResource.read(userID);
  
  return (
    <div>
      <p>name: {data.name}</p>
      <p>age: {data.age}</p>
    </div>
  )
}

可以看到,userResource.read完全是同步写法,其内部会调用fetchUser

背后的逻辑是:

  1. 首次调用userResource.read,会创建一个promise(即fetchUser的返回值)
  2. throw promise
  3. React内部catch promise后,离User组件最近的祖先Suspense组件渲染fallback
  4. promise resolve后,User组件重新render
  5. 此时再调用userResource.read会返回resolve的结果(即fetchUser请求的数据),使用该数据继续render

从步骤1和步骤5可以看出,对于一个请求,userResource.read可能会调用2次,即:

  • 第一次发送请求、返回promise
  • 第二次返回请求到的数据

所以userResource内部需要缓存该promise的值,缓存的key就是userID

const data = userResource.read(userID);

由于userIDUser组件的props,所以当User组件接收不同的userID时,userResource内部需要缓存不同userID对应的promise

如果切换100个userID,就会缓存100个promise。显然我们需要一个缓存清理算法,否则缓存占用会越来越多,直至溢出。

react-cache使用的缓存清理算法就是LRU算法。

LRU原理

LRU(Least recently used,最近最少使用)算法的核心思想是:

如果数据最近被访问过,那么将来被访问的几率也更高

所以,越常被使用的数据权重越高。当需要清理数据时,总是清理最不常使用的数据。

react-cache中LRU的实现

react-cache的实现包括两部分:

  • 数据的存取
  • LRU算法实现

数据的存取

每个通过createResource创建的resource都有一个对应map,其中:

  • mapkeyresource.read(key)执行时传入的key
  • mapvalueresource.read(key)执行后返回的promise

在我们的userResource例子中,createResource执行后会创建map

const userResource = createResource(fetchUser);

userResource.read首次执行后会在该map中设置一条userIDkeypromisevalue的数据(被称为一个entry):

const data = userResource.read(userID);

要获取某个entry,需要知道两样东西:

  • entry对应的key
  • entry所属的resource

如果你想开发小程序或者APP软件的话,可以通过专业开发公司,来帮助你实现开发需求:厦门在乎科技-专注厦门小程序开发、APP开发、网站开发、H5小游戏开发

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-14 22:22:14  更:2021-10-14 22:22:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:17:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码