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知识库 -> React Suspense 在异步获取数据方面的应用 -> 正文阅读

[JavaScript知识库]React Suspense 在异步获取数据方面的应用

写这篇文章之前,实在想吐槽一下 React 官方文档,很多 API 的介绍都是不明不白的,不看之前有一堆问号,看完之后问号更多了。

项目需求

最近在开发一个大数据运维的项目,需要展示大量的 echarts 图表。由于从后台调接口返回数据需要时间,然后前端对数据的处理也需要时间,这样就导致了页面加载的延迟。希望可以做一个整页的 loading ,在图表渲染完成之后展示图表内容。最近在看 ssh 大佬写的一篇文章:

React Suspense + 自定义Hook开启数据请求新方式

看完之后深受启发,希望可以借鉴这个思路实现上述需求。

什么是 React.Suspense

根据 React 官网的介绍,React.Suspense 可以用于在懒加载组件渲染之前先展示一个加载指示器(loading indicator),需要搭配 React.lazy 进行使用:

// 该组件是动态加载的
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    // 显示 <Spinner> 组件直至 OtherComponent 加载完成
    <React.Suspense fallback={<Spinner />}>
      <OtherComponent />
    </React.Suspense>
  );
}

看到这里就有两个问题:

  • React.Suspense 是通过什么机制知道里面异步加载的组件已经加载完毕的;
  • 为什么异步加载的组件要通过 React.lazy 包裹一下(在 Vue 的路由懒加载直接通过 () => import(...) 就可以了);

在 React 官网上有一个说明:

使用 React.lazy 的动态引入特性需要 JS 环境支持 Promise。在 IE11 及以下版本的浏览器中需要通过引入 polyfill 来使用该特性

从上面的描述中可以得知,React.lazy 里面应该是用到了 Promise ,但并不清楚具体的实现机制。

什么是 SWR

首先 swr 是一个用于获取远程数据的 Hooks :

swr - npm

这个库除了 API 的封装比较优雅,更重要的是支持 swr 请求策略。那么 swr 的全称是 stale-while-revalidate ,顾名思义就是重新请求的同时使用过期数据,也就是在发送 HTTP 请求时先返回上一次请求的数据,等后台返回了再把之前的数据替换掉。

SWR 的更多介绍可以看看这篇文章:

谈谈 stale-while-revalidate

这篇文章介绍 swr 这个库,其实想重点介绍里面的一个功能:Suspense mode 。什么意思呢,来看一段官方的代码:

import { Suspense } from 'react'
import useSWR from 'swr'

function Profile() {
  const { data } = useSWR('/api/user', fetcher, { suspense: true })
  return <div>hello, {data.name}</div>
}

function App() {
  return (
    <Suspense fallback={<div>loading...</div>}>
      <Profile/>
    </Suspense>
  )
}

其中 fetcher 是 API 请求的函数封装。useSWR 会把第一个参数作为形参传递给 fetcher ,然后 fetcher 会将请求的结果包裹在 Promise 中返回,下面举个例子:

const fetch = async (params) => {
  // 模拟后台接口响应延迟
  await new Promise(resolve => setTimeout(resolve, 3000));
  return { name: "2333" };
}

当传入的 fetcher 还是 pending 状态时,展示 fallback 中的内容,当状态变为 fullfilled 时渲染子组件。

看到这里可以发现,SWR 的 Suspense mode 和异步组件加载有很多相同之处:

  • 无论 fetcher 还是 import() 都是返回一个 Promise ;
  • 都需要一个函数包裹才能和 React.Suspense 结合使用;

为了搞清楚 Suspense 的机制,其实就是搞清楚 useSWR 里面做了什么。

React.Suspense 原理浅析

原理部分参考了黄子毅大佬的文章,对 API 用法以及一些细节讲得非常详细,推荐看一下:

精读《Hooks 取数 - swr 源码》

这边我们主要关心 Suspense 的实现。Suspense 要求代码 suspended,即要求内部的子组件抛出一个可以被捕获的 Promise 异常,在这个 Promise 结束后再渲染组件。

核心代码就这一段,抛出取数的 Promise:

throw CONCURRENT_PROMISES[key];

等取数完毕后再返回 useSWR API 定义的结构:

return {
  error: latestError,
  data: latestData,
  revalidate,
  isValidating
};

如果没有上面 throw 的一步,在取数完毕前组件就会被渲染出来,所以 throw 了请求的 Promise 使得这个请求函数支持了 Suspense。

总结一下其实就是,useSWR 在数据加载之前先抛出了一个取数的 Promise ,然后 Suspense 内部通过 try...catch 捕获这个 Promise ,然后等待 Promise 状态变为 fullfilled 之后,也就是取数完毕之后,渲染子组件。

那么其实 React.lazy 做的事情也差不多,应该也是抛出一个 Promise (所以文档中提到需要支持 Promise)。然后 Suspense 其实和 ErrorBoundary 很像,不过 Suspense 只负责捕获抛出的 Promise 。

useSWR 使用遇到的问题

看了上面的介绍,useSWR 似乎集众多优点于一身,但是本人使用的时候还是遇到了一点问题:

  • useSWR 必须要传第一个参数,这个参数会作为形参传给 fetch 函数;
  • 如果传空值或者传空字符串,useSWR 不会执行;
  • useSWR 是 hooks ,不能放在函数或者条件判断中;

另外现在项目中都把后端接口的地址和请求方法直接封装进一个函数了,然后调接口的时候直接调用这个函数就行。但是 useSWR 却要在每次请求的时候指定后端接口地址,这样的做法就有点不太合理,实际应用到项目的时候可能需要二次封装。

参考

React Suspense + 自定义Hook开启数据请求新方式
React.Suspence - React 官方文档
swr - npm
谈谈 stale-while-revalidate
精读《Hooks 取数 - swr 源码》

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 16:34:41  更:2021-08-23 16:35:28 
 
开发: 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 12:47:35-

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