From df40749e62408f7586da2142d4afd7b31cb283d1 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Thu, 23 Apr 2026 00:09:11 +0800 Subject: [PATCH] Retry homepage city loading --- frontend/hooks/useDashboardStore.tsx | 32 ++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/frontend/hooks/useDashboardStore.tsx b/frontend/hooks/useDashboardStore.tsx index 3c852473..469a5150 100644 --- a/frontend/hooks/useDashboardStore.tsx +++ b/frontend/hooks/useDashboardStore.tsx @@ -101,8 +101,13 @@ function getInitialProAccessState(): ProAccessState { const SELECTED_CITY_STORAGE_KEY = "polyWeather_selected_city_v1"; const BACKGROUND_SUMMARY_REFRESH_MS = 30_000; +const CITY_LOAD_RETRY_DELAYS_MS = [700, 1600]; type CityDetailDepth = "panel" | "market" | "nearby" | "full"; +function wait(ms: number) { + return new Promise((resolve) => window.setTimeout(resolve, ms)); +} + async function buildAuthMeHeaders(): Promise { const headers: Record = { Accept: "application/json", @@ -349,6 +354,7 @@ export function DashboardStoreProvider({ const summaryInflightByCityRef = useRef>>( {}, ); + const citiesRef = useRef([]); const citySummariesRef = useRef>({}); const selectedCityRef = useRef(null); const selectedDetail = selectedCity ? cityDetailsByName[selectedCity] || null : null; @@ -369,6 +375,10 @@ export function DashboardStoreProvider({ proAccess.subscriptionActive, ]); + useEffect(() => { + citiesRef.current = cities; + }, [cities]); + useEffect(() => { citySummariesRef.current = citySummariesByName; }, [citySummariesByName]); @@ -614,9 +624,24 @@ export function DashboardStoreProvider({ const loadCities = async () => { setLoadingState((current) => ({ ...current, cities: true })); + let lastError: unknown = null; try { - const nextCities = await dashboardClient.getCities(); - setCities(nextCities); + for (let attempt = 0; attempt <= CITY_LOAD_RETRY_DELAYS_MS.length; attempt += 1) { + try { + const nextCities = await dashboardClient.getCities(); + if (!nextCities.length) { + throw new Error("City list was empty"); + } + setCities(nextCities); + return; + } catch (error) { + lastError = error; + const delayMs = CITY_LOAD_RETRY_DELAYS_MS[attempt]; + if (delayMs == null) break; + await wait(delayMs); + } + } + console.error("Failed to load monitored cities", lastError); } finally { setLoadingState((current) => ({ ...current, cities: false })); } @@ -920,6 +945,9 @@ export function DashboardStoreProvider({ dashboardClient.clearCityDetailCache(); setCityDetailsByName({}); setCityDetailMetaByName({}); + if (!citiesRef.current.length) { + await loadCities(); + } if (selectedCity) { const access = proAccessRef.current; setLoadingState((current) => ({ ...current, refresh: true }));