<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我對請求做了個(gè)性能小優(yōu)化,提升了50%的頁面性能

          共 5913字,需瀏覽 12分鐘

           ·

          2023-09-25 14:56


          背景

          最近海外應(yīng)用有某些用戶反饋,打開頁面比較卡頓,后來針對這個(gè)問題做了層優(yōu)化

          問題

          這里我們用微信好友列表為例子,因?yàn)榱斜砉δ鼙容^常見,詳細(xì)分析下常見項(xiàng)目存在的一些問題,以及如何優(yōu)化

          image.png

          通常我們的項(xiàng)目中都是有列表這種場景,然后點(diǎn)擊列表里面的具體item,就去到具體的詳情頁

          image.png

          我們可能是這么處理

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

          然后我們點(diǎn)擊好友列表進(jìn)入具體的詳情頁根據(jù)useId再去拿具體的信息

          getUserInfoById(id)

          預(yù)加載

          但是這里就會(huì)存在一個(gè),進(jìn)入詳情頁的時(shí)候,打開會(huì)慢,所以這里一般會(huì)先做數(shù)據(jù)預(yù)加載,也就是在好友列表的時(shí)候我就想拿到這個(gè)詳情頁數(shù)據(jù),這時(shí)候我們可能這么處理

          一次性返回?cái)?shù)據(jù)

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

          后端支持在好友列表的時(shí)候同時(shí)返回具體的detail信息,這樣就不用去走一次getUserInfoById(id),但是這里也會(huì)存在一個(gè)問題,好友列表這個(gè)接口太冗余,而且數(shù)據(jù)量太大,打開頁面的時(shí)候也會(huì)出現(xiàn)加載慢的場景,所以這個(gè)策略也只能針對數(shù)據(jù)量較小的情況采取

          預(yù)加載getUserInfoById接口

          image.png

          那么干脆一點(diǎn),我們請求完好友接口后,再根據(jù)用戶Id,在App下偷偷請求getUserInfoById接口

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

          這樣就會(huì)出現(xiàn)一個(gè)問題,后端服務(wù)可能扛不住我們這樣頻繁的請求,所以有什么辦法解決呢?那就是請求合并將多個(gè)重復(fù)請求(參數(shù)不一樣),合并成一個(gè),也就是將參數(shù)合并

          請求合并

          const fetchUserInfoBatched = createBatchedRequest<string, UserBaseInfo>(
            async (userIds) => {
              const { data } = await request.post('/api/user/list', {
                userIds,
              });
              return data;
            },
            500 // 設(shè)置延遲時(shí)間為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;
          }

          /**
           * 創(chuàng)建批量請求的函數(shù)
           * 在一定延遲時(shí)間內(nèi)的所有請求都會(huì)被合并提交并批量發(fā)送
           * @param batchFunction 合并后的請求函數(shù)
           * @param delay 延遲時(shí)間,以毫秒為單位
           */

          export function createBatchedRequest<TR>(
            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 函數(shù)用于管理批量請求,它可以將多個(gè)獨(dú)立的請求合并成一個(gè)批量請求,以減少不必要的網(wǎng)絡(luò)請求次數(shù)。

          • 參數(shù)說明:

            • batchFunction 參數(shù)是一個(gè)函數(shù),接受一個(gè)數(shù)組 batchParams 作為參數(shù),返回一個(gè) Promise,用于處理合并后的請求并返回結(jié)果。
            • delay 參數(shù)表示延遲時(shí)間,以毫秒為單位。在指定的延遲時(shí)間內(nèi),所有的請求會(huì)被收集起來,然后一次性發(fā)送給 batchFunction 處理。
          • 請求隊(duì)列: 函數(shù)內(nèi)部維護(hù)一個(gè)請求隊(duì)列 batchQueue,用于存儲(chǔ)待合并的請求項(xiàng)。每個(gè)請求項(xiàng)包含了請求的參數(shù)、成功回調(diào)函數(shù) resolve 和失敗回調(diào)函數(shù) reject

          • 執(zhí)行批量請求:

            • 當(dāng)有請求調(diào)用返回的函數(shù)時(shí),它會(huì)將請求參數(shù)和相應(yīng)的回調(diào)函數(shù)添加到請求隊(duì)列 batchQueue 中。
            • 使用定時(shí)器控制,在指定的延遲時(shí)間后,會(huì)執(zhí)行 executeBatchedRequest 函數(shù)。
            • executeBatchedRequest 函數(shù)會(huì)檢查是否已經(jīng)有批量請求正在處理(isBatching 標(biāo)志),如果有,則不進(jìn)行處理,直到當(dāng)前批量請求完成。
            • 如果沒有正在處理的批量請求,它會(huì)取出請求隊(duì)列中的所有請求項(xiàng),合并參數(shù)后調(diào)用 batchFunction 處理請求。
            • 成功或失敗后,會(huì)分別調(diào)用請求項(xiàng)中的 resolvereject 回調(diào)函數(shù),將結(jié)果返回給每個(gè)獨(dú)立的請求。
          - END -


          瀏覽 915
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩中文字幕视频在线观看 | 秋霞操逼| 黄色一级免费看 | 一级a一级a免费视频 | 国产微拍精品一区 |