diff --git a/static/js/history.js b/static/js/history.js index fc1697b..1fce36b 100644 --- a/static/js/history.js +++ b/static/js/history.js @@ -33,7 +33,8 @@ let _geoTimer = null; let _lastGeoKey = null; - let _geoCache = {}; // key → label, pre-populated on trip load + let _geoCache = {}; + let _preloadController = null; function _geoKey(lat, lon) { const la = typeof lat === 'number' ? lat : parseFloat(lat); @@ -43,16 +44,17 @@ } function preloadGeocodes(points) { - // Pre-fetch geocode labels for all unique coordinates with a small - // concurrency cap so the server (which uses slow Nominatim) doesn't - // get overwhelmed. The Pi's reverse_geocoder is instant, so this - // still works fast there. + // Abort any in-flight preload from a previous trip selection. + if (_preloadController) _preloadController.abort(); + _preloadController = new AbortController(); + const signal = _preloadController.signal; + _geoCache = {}; const seen = new Set(); const queue = []; for (const p of points) { const key = _geoKey(p.latitude, p.longitude); - if (seen.has(key)) continue; + if (!key || seen.has(key)) continue; seen.add(key); queue.push({ key, lat: p.latitude, lon: p.longitude }); } @@ -61,17 +63,18 @@ const CONCURRENCY = 2; let idx = 0; function next() { - if (idx >= queue.length) return; + if (idx >= queue.length || signal.aborted) return; const item = queue[idx++]; const ctrl = new AbortController(); const t = setTimeout(() => ctrl.abort(), 3000); + signal.addEventListener('abort', () => ctrl.abort()); fetch(`/api/geocode?lat=${item.lat}&lon=${item.lon}`, { signal: ctrl.signal }) .then(r => { clearTimeout(t); return r.ok ? r.json() : null; }) .then(data => { - _geoCache[item.key] = (data && data.label) || null; + if (!signal.aborted) _geoCache[item.key] = (data && data.label) || null; }) .catch(() => { clearTimeout(t); }) - .finally(() => next()); + .finally(() => { if (!signal.aborted) next(); }); } for (let i = 0; i < CONCURRENCY && i < queue.length; i++) next(); }