Просмотр исходного кода

perf: 费率策略增加 10 分钟缓存并分批并发请求,消除地图/列表刷新时的 N+1 请求

skyline 3 недель назад
Родитель
Сommit
7f02d99dfa
1 измененных файлов с 43 добавлено и 18 удалено
  1. 43 18
      charge-front/src/api/charge.ts

+ 43 - 18
charge-front/src/api/charge.ts

@@ -36,7 +36,16 @@ export async function changeAppointmentTime(
     );
 }
 
+// 费率策略缓存:同一桩的分时电价短期不变,
+// 避免地图/列表每次刷新都逐站请求 businessPolicy(N+1 请求风暴)
+const _priceCache = new Map<string, { data: any; ts: number }>();
+const PRICE_CACHE_TTL = 10 * 60 * 1000;
+
 export function fetchStationPriceDesc(ConnectorID: string, StationID?: string) {
+    const cached = _priceCache.get(ConnectorID);
+    if (cached && Date.now() - cached.ts < PRICE_CACHE_TTL) {
+        return Promise.resolve({ ...cached.data });
+    }
     return cHttp.get(`/charge/businessPolicy/${ConnectorID}`).then((res) => {
         const nowHour = new Date().getHours();
         let maxPrice = 0;
@@ -93,6 +102,7 @@ export function fetchStationPriceDesc(ConnectorID: string, StationID?: string) {
         if (StationID) {
             res.StationID = StationID;
         }
+        _priceCache.set(ConnectorID, { data: res, ts: Date.now() });
         return res;
     });
 }
@@ -169,7 +179,6 @@ export function fetchStations(
 ): Promise<any[]> {
     return fetchAllStations(latitude, longitude)
         .then((res) => {
-            // console.log(latitude, longitude);
             // let list = JSON.parse(JSON.stringify(res));
             const data: any[] = JSON.parse(JSON.stringify(res)); // []
             const start = (page - 1) * pageSize;
@@ -363,7 +372,6 @@ export function fetchStationDetail(stationId: string) {
     return cHttp
         .get(`/charge/stationInfo/${stationId}`)
         .then((res) => {
-            console.log("xxxxx", res)
             return res;
         });
 }
@@ -425,7 +433,6 @@ export function fetchStationByConnectorIdOrShortId(sn: string) {
     return fetchAllStations()
         .then((res) => {
             let station: any = undefined;
-            console.log("fetchStationByConnectorIdOrShortId", res)
             res.forEach((item) => {
                 if (!station && item.equipmentInfos && item.equipmentInfos) {
                     item.equipmentInfos.forEach(
@@ -475,11 +482,9 @@ export function fetchStationByConnectorIdOrShortId(sn: string) {
 export function searchStation(keyword: string) {
     return fetchAllStations().then((res) => {
         // const reg = new RegExp(keyword.trim(), "ig");
-        // console.log(res)
         const stationIdList = res.filter(
             (item) => item.stationName.includes(keyword) || item.address.includes(keyword)
         ).map(k => k.stationId+"");
-        // console.log("serach>>>>>",list)
         if (stationIdList) {
             let {latitude, longitude} = getApp<any>().globalData.fetchLocation
             return _fetchStations(1, 100, latitude, longitude,  stationIdList)
@@ -509,7 +514,6 @@ export function fetchAllStations(latitude?: number, longitude?: number): Promise
                 //     StationID: '0000'
                 //   })
                 // }
-                console.log("所有电站数据", list);
                 getApp<any>().globalData.stations = list;
                 resolve(list);
             })
@@ -540,7 +544,6 @@ export function _fetchStations(page: number, pageSize: number,
     return cHttp
         .get(`/charge/listStation?pageNum=${page}&pageSize=${pageSize}&latitude=${latitude||22.696779}&longitude=${longitude||114.044805}&stationIdList=${stationIdList||[]}`)
         .then((res) => {
-            // console.log("xxxxx", res)
             const data = res.list || [];
             data.forEach((item: any) => {
                 item.StationID = item.stationId;
@@ -578,23 +581,44 @@ export function _getDistance(lat1: number, lng1: number, lat2: number, lng2: num
     return s;
 }
 
+// 并发分批执行:避免几十个费率请求同时发出(微信原生并发上限 10)
+const PRICE_CONCURRENCY = 8;
+
+function _runInBatches(tasks: (() => Promise<any>)[], size: number): Promise<any[]> {
+    const results: any[] = [];
+    let index = 0;
+    const runNext = (): Promise<void> => {
+        if (index >= tasks.length) {
+            return Promise.resolve();
+        }
+        const current = index++;
+        return tasks[current]().then((r) => {
+            results[current] = r;
+            return runNext();
+        });
+    };
+    return Promise.all(
+        Array.from({ length: Math.min(size, tasks.length) }, runNext)
+    ).then(() => results);
+}
+
 function _fetchStationStatus(list: any[]) {
     if (list.length <= 0) {
         return Promise.resolve([]);
     }
     let _list: any[] = [];
-    return cHttp
-        .get(
-            `/charge/stationStatus?stationIds=${list
-                .filter((item) => item.StationID !== "0000")
-                .map((item) => item.StationID)
-                .join(",")}`
-        )
+    const stationIdQuery = list
+        .filter((item) => item.StationID !== "0000")
+        .map((item) => item.StationID)
+        .join(",");
+    const statusPromise: Promise<any> = stationIdQuery
+        ? cHttp.get(`/charge/stationStatus?stationIds=${stationIdQuery}`)
+        : Promise.resolve([]);
+    return statusPromise
         .then((res) => {
             const StationStatusInfos = res || [];
             const ConnectorIDs: string[] = [];
             const StationIDs: string[] = [];
-            console.log("_fetchStationStatus", list)
             list.forEach((item: any) => {
                 item.fastEquipmentInfos = [];
                 item.slowEquipmentInfos = [];
@@ -629,10 +653,11 @@ function _fetchStationStatus(list: any[]) {
                 }
             });
             _list = list;
-            return Promise.all(
+            return _runInBatches(
                 ConnectorIDs.map((cid, cindex) => {
-                    return fetchStationPriceDesc(cid, StationIDs[cindex]);
-                })
+                    return () => fetchStationPriceDesc(cid, StationIDs[cindex]);
+                }),
+                PRICE_CONCURRENCY
             );
         })
         .then((res) => {