理解并预防 React 中的 Fetch Waterfalls

如果您是 React 开发人员,那么您肯定遇到过获取瀑布(也称为请求瀑布或网络瀑布)。当您尝试查看是什么导致您精心设计的页面加载时间如此之长时,它们独特的形状就会出现在分析工具中。

在这篇博文中,我们将讨论什么是获取瀑布、为什么会发生、它们如何影响你的 React 应用程序,以及最重要的是,如何避免它们。

什么是 Fetch Waterfall?

让我们从基础开始。

抓取瀑布是一种性能问题,当多个 API 调用或抓取请求串联在一起并逐个执行时就会发生这种情况。这些请求不是并行发送(这样它们就可以同时完成),而是排队并按顺序执行。这会导致页面呈现明显延迟,尤其是在抓取次数增加的情况下。

以下是一个简单的视觉表示:

Network tab of dev tools showing fetch waterfall

来源:Sentry.io

从上图中,您可以清楚地看到“瀑布”模式中的**连续延迟**。每个请求仅在前一个请求完成后才开始。实际上,即使一个请求稍微延迟也会导致整个页面加载时间急剧增加。

这对用户体验来说尤其麻烦,因为现代网络用户期望应用程序快速加载。几秒钟的延迟可能会导致**更高的跳出率**和**更低的参与度**,从而影响应用程序的整体成功。

为什么会出现 Fetch Falls?

React 中的 Fetch 瀑布通常是由于组件的层级结构而发生的。以下是一个典型的场景:

  • 父组件获取数据:父组件挂载的时候,发起获取请求。
  • 子组件等待数据:子组件依赖于父组件获取的数据,并且仅在父组件的数据可用后才会呈现。
  • 顺序请求:如果有多个嵌套组件,每个组件可能会顺序触发获取请求,从而导致“瀑布”效果。
  • 这种级联行为的发生是因为 React 中的组件是异步渲染的。当父组件获取数据时,子组件可能必须等到父组件的请求完成。如果这些获取操作处理得不到有效,最终可能会出现显著的延迟,因为每个请求都依赖于前一个请求。

    如何识别获取瀑布

    要确定您的 React 应用程序是否受到抓取瀑布的影响,您可以使用 **Chrome DevTools** 或 **React DevTools** 等工具来监控网络请求和性能。在 Chrome DevTools 中,导航到 **网络** 选项卡并查找阻碍页面加载过程的 **连续 API 调用**。

    在 React DevTools 中,您可以检查组件重新渲染并识别导致多次触发获取请求的任何不必要的依赖项。

    以下是可能出现水位瀑布的一些迹象:

  • 页面加载时间缓慢:如果您的页面加载时间比预期的要长。
  • 可疑的性能模式:如果您注意到一系列 API 调用似乎是一个接一个进行的,而不是并行进行的。
  • 如何防止 React 中的瀑布式获取

    幸运的是,有几种策略可以避免获取瀑布并优化你的 React 应用程序以获得更好的性能。

    1. 并行获取数据

    不要等待每个 API 请求完成后再开始下一个请求,可以考虑并行执行多个获取请求。这可以使用 JavaScript 的“Promise.all()”方法来实现,该方法允许您同时运行多个承诺。

    以下是并行获取数据的示例:

    const fetchData = async () => {
    const [data1, data2, data3] = await Promise.all([
      fetch('/api/data1').then(res => res.json()),
      fetch('/api/data2').then(res => res.json()),
      fetch('/api/data3').then(res => res.json()),
    ]);
    // Use the data
    };

    通过并行获取数据,您可以减少总等待时间并允许浏览器更快地加载资源。

    2. 解耦组件数据获取

    您可以重构组件,使它们不依赖父组件的数据来触发自己的数据获取。相反,让每个子组件独立处理自己的数据获取。这可以通过**提升状态**并向下传递必要的数据来实现,也可以通过使用**React Query**或**SWR**等库来管理组件级别的获取。

    3.使用 React Query 或 SWR

    **React Query** 和 **SWR** 等库非常适合管理 React 应用程序中的数据获取。它们处理缓存、后台数据获取和错误处理,同时还允许您高效地并行获取数据。

    例如,React Query 会自动处理数据获取的缓存、重试和后台同步,确保您的组件不会不必要地等待数据,并且仅在需要时进行网络调用。

    import { useQuery } from 'react-query';
    const fetchData = async () => {
    const res = await fetch('/api/data');
    return res.json();
    };
    
    const MyComponent = () => {
    const { data, isLoading } = useQuery('dataKey', fetchData);
    
    if (isLoading) return 
    Loading...
    ; return
    Data: {JSON.stringify(data)}
    ; };

    4.缓存数据以减少冗余请求

    缓存可以显著减少对服务器的冗余请求。通过在本地存储获取的数据(在组件状态、上下文或**React Query**等缓存库中),您可以避免不必要的网络请求,从而使您的应用程序更快、更高效。

    结论

    React 中的获取瀑布可能是性能瓶颈的主要来源,但只要采取正确的策略,就可以轻松避免。通过并行获取数据、将数据获取与组件分离以及利用 React Query 等强大的库,您可以提高 React 应用程序的性能并增强用户体验。

    如果您在 React 代码库中频繁出现抓取瀑布,则值得退后一步来分析数据抓取模式并实施这些最佳实践。最终,优化应用程序与 API 的交互方式将带来更快、更可靠、更可扩展的应用程序。