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

小册

这是我整理的学习资料,非常系统和完善,欢迎一起学习

背景

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

问题

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

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

我们可能是这么处理

tsx 复制代码
<List>
    {
      list.map((item)=><ListItem id={Item.useId}/>)
    } 
</List>

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

ts 复制代码
getUserInfoById(id)

预加载

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

一次性返回数据

tsx 复制代码
<List>
    {
      list.map((item)=><ListItem detail={Item.detail}/>)
    } 
</List>

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

预加载getUserInfoById接口

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

ts 复制代码
getUserInfoById(1)
getUserInfoById(2)
getUserInfoById(3)
...

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

请求合并

ts 复制代码
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

ts 复制代码
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 回调函数,将结果返回给每个独立的请求。

面试

最近整理了一套面试小册,有在线版和离线版本

离线版本效果如下,可添加微信linwu-hi获取,阅读效果非常不错

相关推荐
Martin -Tang34 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发35 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁2 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂2 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成5 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽5 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新6 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html