perf: add sessionStorage caching to avoid re-fetching data when navigating back
This commit is contained in:
@@ -10,6 +10,31 @@
|
|||||||
let map = null;
|
let map = null;
|
||||||
let markers = {}; // cityName → Leaflet marker
|
let markers = {}; // cityName → Leaflet marker
|
||||||
let cityDataCache = {}; // cityName → API response
|
let cityDataCache = {}; // cityName → API response
|
||||||
|
const CACHE_KEY = "polyWeather_v1";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cachedStr = sessionStorage.getItem(CACHE_KEY);
|
||||||
|
if (cachedStr) {
|
||||||
|
const parsed = JSON.parse(cachedStr);
|
||||||
|
if (Date.now() - parsed.timestamp < 5 * 60 * 1000) {
|
||||||
|
cityDataCache = parsed.data || {};
|
||||||
|
} else {
|
||||||
|
sessionStorage.removeItem(CACHE_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Restore cache failed", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveCache() {
|
||||||
|
try {
|
||||||
|
sessionStorage.setItem(
|
||||||
|
CACHE_KEY,
|
||||||
|
JSON.stringify({ timestamp: Date.now(), data: cityDataCache }),
|
||||||
|
);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
let selectedCity = null;
|
let selectedCity = null;
|
||||||
let tempChart = null;
|
let tempChart = null;
|
||||||
const AUTO_REFRESH_MS = 60 * 60 * 1000; // 1 hour
|
const AUTO_REFRESH_MS = 60 * 60 * 1000; // 1 hour
|
||||||
@@ -208,11 +233,26 @@ async function loadCityDetail(cityName) {
|
|||||||
selectedCity = cityName;
|
selectedCity = cityName;
|
||||||
setActiveCityItem(cityName);
|
setActiveCityItem(cityName);
|
||||||
setSelectedMarker(cityName);
|
setSelectedMarker(cityName);
|
||||||
|
|
||||||
|
if (cityDataCache[cityName]) {
|
||||||
|
renderPanel(cityDataCache[cityName]);
|
||||||
|
const cData = cityDataCache[cityName];
|
||||||
|
if (cData.lat != null && cData.lon != null) {
|
||||||
|
map.flyTo([cData.lat, cData.lon], 10, {
|
||||||
|
animate: true,
|
||||||
|
duration: 1.5,
|
||||||
|
easeLinearity: 0.25,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
showLoading(true);
|
showLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await fetchCityDetail(cityName);
|
const data = await fetchCityDetail(cityName);
|
||||||
cityDataCache[cityName] = data;
|
cityDataCache[cityName] = data;
|
||||||
|
saveCache();
|
||||||
renderPanel(data);
|
renderPanel(data);
|
||||||
|
|
||||||
// Cinematic Zoom-in Camera
|
// Cinematic Zoom-in Camera
|
||||||
@@ -794,6 +834,7 @@ async function loadAllCitiesProgressively(cities) {
|
|||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
cityDataCache[city.name] = data;
|
cityDataCache[city.name] = data;
|
||||||
|
saveCache();
|
||||||
|
|
||||||
// 如果用户目前没有点击它,仅更新标记和列表
|
// 如果用户目前没有点击它,仅更新标记和列表
|
||||||
if (data.current?.temp != null) {
|
if (data.current?.temp != null) {
|
||||||
@@ -1010,6 +1051,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
const btn = document.getElementById("refreshAllBtn");
|
const btn = document.getElementById("refreshAllBtn");
|
||||||
btn.classList.add("spinning");
|
btn.classList.add("spinning");
|
||||||
cityDataCache = {};
|
cityDataCache = {};
|
||||||
|
saveCache();
|
||||||
if (selectedCity) {
|
if (selectedCity) {
|
||||||
await loadCityDetail(selectedCity);
|
await loadCityDetail(selectedCity);
|
||||||
}
|
}
|
||||||
@@ -1019,9 +1061,26 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
// Load cities
|
// Load cities
|
||||||
const cities = await fetchCities();
|
const cities = await fetchCities();
|
||||||
if (cities.length > 0) {
|
if (cities.length > 0) {
|
||||||
|
cities.forEach((c) => {
|
||||||
|
const cached = cityDataCache[c.name];
|
||||||
|
if (cached && cached.current?.temp != null) {
|
||||||
|
c._temp =
|
||||||
|
cached.current.max_so_far != null &&
|
||||||
|
cached.current.max_so_far >= cached.current.temp
|
||||||
|
? cached.current.max_so_far
|
||||||
|
: cached.current.temp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
addCityMarkers(cities);
|
addCityMarkers(cities);
|
||||||
buildCityList(cities);
|
buildCityList(cities);
|
||||||
|
|
||||||
|
cities.forEach((c) => {
|
||||||
|
if (cityDataCache[c.name]) {
|
||||||
|
updateCityListInfo(cityDataCache[c.name]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Fit map to show all markers
|
// Fit map to show all markers
|
||||||
const bounds = cities.map((c) => [c.lat, c.lon]);
|
const bounds = cities.map((c) => [c.lat, c.lon]);
|
||||||
map.fitBounds(bounds, { padding: [60, 60], maxZoom: 4 });
|
map.fitBounds(bounds, { padding: [60, 60], maxZoom: 4 });
|
||||||
|
|||||||
Reference in New Issue
Block a user