我对请求做了个性能小优化,提升了50%的页面性能

简介: 我对请求做了个性能小优化,提升了50%的页面性能

背景


最近海外应用有某些用户反馈,打开页面比较卡顿,后来针对这个问题做了层优化


问题


这里我们用微信好友列表为例子,因为列表功能比较常见,详细分析下常见项目存在的一些问题,以及如何优化

image.png

通常我们的项目中都是有列表这种场景,然后点击列表里面的具体item,就去到具体的详情页

https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1334d2d129724923a0ecbddeaa0c3b71~tplv-k3u1fbpfcp-jj-mark:3024:0:0:0:q75.awebp#?w=1170&h=1402&s=183606&e=jpg&b=fdfcfc

我们可能是这么处理

<List>
    {
      list.map((item)=><ListItem id={Item.useId}/>)
    } 
</List>

然后我们点击好友列表进入具体的详情页根据useId再去拿具体的信息

getUserInfoById(id)


预加载


但是这里就会存在一个,进入详情页的时候,打开会慢,所以这里一般会先做数据预加载,也就是在好友列表的时候我就想拿到这个详情页数据,这时候我们可能这么处理


一次性返回数据


<List>
    {
      list.map((item)=><ListItem detail={Item.detail}/>)
    } 
</List>

后端支持在好友列表的时候同时返回具体的detail信息,这样就不用去走一次getUserInfoById(id),但是这里也会存在一个问题,好友列表这个接口太冗余,而且数据量太大,打开页面的时候也会出现加载慢的场景,所以这个策略也只能针对数据量较小的情况采取


预加载getUserInfoById接口


image.png

那么干脆一点,我们请求完好友接口后,再根据用户Id,在App下偷偷请求getUserInfoById接口

getUserInfoById(1)
getUserInfoById(2)
getUserInfoById(3)
...

这样就会出现一个问题,后端服务可能扛不住我们这样频繁的请求,所以有什么办法解决呢?那就是请求合并将多个重复请求(参数不一样),合并成一个,也就是将参数合并


请求合并


const fetchUserInfoBatched = createBatchedRequest<string, UserBaseInfo>(
  async (userIds) => {
    const { data } = await request.post('/api/user/list', {
      userIds,
    });
    return data;
  },
  500 // 设置延迟时间为500毫秒
);
// 使用示例
async function getUserInfo() {
  const user1 = await fetchUserInfoBatched(1);
  const user2 = await fetchUserInfoBatched(2);
  const user3 = await fetchUserInfoBatched(3);
  console.log(user1, user2, user3);
}
getUserInfo();


createBatchedRequest


interface BatchRequestItem<T, R> {
  params: T;
  resolve: (r: R) => void;
  reject: (reason: unknown) => void;
}
/**
 * 创建批量请求的函数
 * 在一定延迟时间内的所有请求都会被合并提交并批量发送
 * @param batchFunction 合并后的请求函数
 * @param delay 延迟时间,以毫秒为单位
 */
export function createBatchedRequest<T, R>(
  batchFunction: (batchParams: T[]) => Promise<R[]>,
  delay = 200
): (params: T) => Promise<R> {
  const batchQueue: BatchRequestItem<T, R>[] = [];
  let isBatching = false;
  let timer: NodeJS.Timeout | null = null;
  async function executeBatchedRequest() {
    if (isBatching) return;
    isBatching = true;
    const itemsToBatch = [...batchQueue];
    batchQueue.length = 0;
    try {
      const batchedResult = await batchFunction(itemsToBatch.map((item) => item.params));
      itemsToBatch.forEach((item, index) => {
        item.resolve(batchedResult[index]);
      });
    } catch (error) {
      itemsToBatch.forEach((item) => {
        item.reject(error);
      });
    } finally {
      isBatching = false;
    }
  }
  return (params: T): Promise<R> => {
    return new Promise<R>((resolve, reject) => {
      batchQueue.push({
        params,
        resolve,
        reject,
      });
      // Execute the batched request after the specified delay
      if (!timer) {
        timer = setTimeout(() => {
          executeBatchedRequest();
          timer = null;
        }, delay);
      }
    });
  };
}
  • 批量请求管理: createBatchedRequest 函数用于管理批量请求,它可以将多个独立的请求合并成一个批量请求,以减少不必要的网络请求次数。
  • 参数说明:
  • batchFunction 参数是一个函数,接受一个数组 batchParams 作为参数,返回一个 Promise,用于处理合并后的请求并返回结果。
  • delay 参数表示延迟时间,以毫秒为单位。在指定的延迟时间内,所有的请求会被收集起来,然后一次性发送给 batchFunction 处理。
  • 请求队列: 函数内部维护一个请求队列 batchQueue,用于存储待合并的请求项。每个请求项包含了请求的参数、成功回调函数 resolve 和失败回调函数 reject
  • 执行批量请求:
  • 当有请求调用返回的函数时,它会将请求参数和相应的回调函数添加到请求队列 batchQueue 中。
  • 使用定时器控制,在指定的延迟时间后,会执行 executeBatchedRequest 函数。
  • executeBatchedRequest 函数会检查是否已经有批量请求正在处理(isBatching 标志),如果有,则不进行处理,直到当前批量请求完成。
  • 如果没有正在处理的批量请求,它会取出请求队列中的所有请求项,合并参数后调用 batchFunction 处理请求。
  • 成功或失败后,会分别调用请求项中的 resolvereject 回调函数,将结果返回给每个独立的请求。


面试


目录
相关文章
|
4月前
|
缓存 前端开发 JavaScript
如何优化前端页面性能
前端性能优化是网站开发中非常重要的一部分,它直接关系到用户体验和网站的流量以及排名。本文将介绍一些优化前端页面性能的方法,包括减少HTTP请求、压缩代码、使用CDN等。
|
11月前
|
存储 编译器
深入解析i++和++i的区别及性能影响
在我们编写代码时,经常需要对变量进行自增操作。这种情况下,我们通常会用到两种常见的操作符:i++和++i。最近在阅读博客时,我偶然看到了有关i++和++i性能的讨论。之前我一直在使用它们,但从未从性能的角度考虑过,这让我突然产生了兴趣。尽管它们看起来相似,但它们之间存在微妙而重要的区别。在本文中,我们将详细解释i++和++i之间的区别,以及它们对代码性能的影响。
336 1
深入解析i++和++i的区别及性能影响
|
9天前
|
缓存 监控 前端开发
多个异步操作对网页性能的影响及优化建议
多个异步操作会影响网页性能,主要体现在网络请求延迟、资源竞争及浏览器限制等方面,可能导致页面加载缓慢。为优化性能,可采用 `Promise.all()` 并行处理、请求合并、懒加载、缓存利用、CDN 托管、请求优化及性能监控等策略,从而提升用户体验。
|
3天前
|
JavaScript 前端开发 数据库
优化后端性能:如何使用异步编程提升系统响应速度
异步编程已成为现代后端系统性能优化的重要策略。通过避免阻塞操作,异步编程可以显著提高系统的响应速度和并发处理能力。本文章深入探讨了异步编程的基本概念,比较了常见的异步编程模型,并通过实际案例演示如何在Node.js和Python中实现异步操作,以提升系统性能。
|
4月前
|
Dubbo Java 测试技术
性能基础之浅谈常见接口性能压测
【4月更文挑战第26天】性能基础之浅谈常见接口性能压测
89 1
性能基础之浅谈常见接口性能压测
|
4月前
|
存储 缓存 负载均衡
优化服务器响应时间的方法如下
【4月更文挑战第25天】
80 5
|
4月前
|
缓存 前端开发 JavaScript
如何优化前端网页性能
网页性能是用户体验的重要因素之一,许多因素会影响网页的性能,包括加载时间、响应速度和渲染时间等。本文将介绍如何优化前端网页性能,从减少HTTP请求数、压缩资源、使用CDN以及异步加载等方面入手,为读者提供实用的技巧和建议。
|
10月前
|
存储 缓存 Linux
高效利用CPU缓存一致性:优化技巧与策略分析
高效利用CPU缓存一致性:优化技巧与策略分析
|
Web App开发 Java Linux
【性能优化】使用Perfetto定位应用启动性能的瓶颈
本篇文章将会结合我个人对Perfetto的实际使用经历,讲解车载应用的启动时间是如何测量得到的,测量出启动时间后,我们又该如何找出其中的性能瓶颈。
1618 1
【性能优化】使用Perfetto定位应用启动性能的瓶颈
|
存储 缓存 前端开发
前端性能优化之请求优化
前端页面使用场景多变,受外界因素影响较多,网络环境,用户设备,浏览器内核等都会影响性能体验。所以针对每一个请求都要想想是否有优化的空间,是否有省去的可能,让每发起一个请求都尽其所能,达到请求的极致。
1863 0