fix(map): two-layer cancel token system to fully prevent orphan markers/polylines on banner close
This commit is contained in:
@ -31,7 +31,8 @@ export const useFlujoPrincipal = () => {
|
||||
map: google.maps.Map | undefined,
|
||||
addCleanMarker: Function,
|
||||
skipGuidedZoom = false,
|
||||
onStopClick?: (stop: BusStop) => void
|
||||
onStopClick?: (stop: BusStop) => void,
|
||||
cancelToken?: { cancelled: boolean } // token de cancelación pasado desde el llamador
|
||||
) => {
|
||||
if (!map) return
|
||||
|
||||
@ -50,6 +51,13 @@ export const useFlujoPrincipal = () => {
|
||||
paradasExistentes.length > 0 ? Promise.resolve(paradasExistentes) : routeStore.loadRouteStops(_ruta.id)
|
||||
]);
|
||||
|
||||
// Guard: abandono si el token fue cancelado o la ruta ya no está activa
|
||||
if (cancelToken?.cancelled || routeStore.selectedRouteId !== _ruta.id) {
|
||||
console.log('SIBU | procesarSeleccionDeRuta abortado tras Promise.allSettled (ruta ya no activa o cancelada)');
|
||||
limpiarMapa(); // limpiar cualquier polyline ya dibujada
|
||||
return;
|
||||
}
|
||||
|
||||
// ── PASO 3: Asignación Segura ──
|
||||
let ubicacion: { lat: number, lng: number } | null = null;
|
||||
if (ubicacionRes.status === 'fulfilled') {
|
||||
@ -58,12 +66,6 @@ export const useFlujoPrincipal = () => {
|
||||
console.warn('SIBU | GPS falló o fue denegado');
|
||||
}
|
||||
|
||||
// Guard contra race condition: si el usuario cerró el banner mientras cargaba
|
||||
if (routeStore.selectedRouteId !== _ruta.id) {
|
||||
console.log('SIBU | Carga abortada: La ruta ya no está seleccionada.');
|
||||
return;
|
||||
}
|
||||
|
||||
let paradas: BusStop[] = [];
|
||||
if (paradasRes.status === 'fulfilled') {
|
||||
// Si loadRouteStops no devolviera los datos directamente, los tomamos del store
|
||||
@ -86,6 +88,7 @@ export const useFlujoPrincipal = () => {
|
||||
// Si no detectamos GPS, trazamos la ruta completa sin zoom guiado
|
||||
if (!ubicacion) {
|
||||
await trazarRuta(paradasFormateadas, map, false);
|
||||
if (cancelToken?.cancelled) { limpiarMapa(); return; }
|
||||
const bounds = new google.maps.LatLngBounds()
|
||||
paradasFormateadas.forEach(p => bounds.extend(new google.maps.LatLng(p.latitud, p.longitud)))
|
||||
map.fitBounds(bounds, { top: 100, bottom: 100, left: 60, right: 60 })
|
||||
@ -93,11 +96,19 @@ export const useFlujoPrincipal = () => {
|
||||
}
|
||||
|
||||
// ── PASO 4: Dibujar y Renderizar ──
|
||||
if (routeStore.selectedRouteId !== _ruta.id) return;
|
||||
if (cancelToken?.cancelled || routeStore.selectedRouteId !== _ruta.id) {
|
||||
limpiarMapa();
|
||||
return;
|
||||
}
|
||||
|
||||
// Dibujar ruta completa (fondo)
|
||||
await trazarRuta(paradasFormateadas, map, true);
|
||||
|
||||
if (cancelToken?.cancelled || routeStore.selectedRouteId !== _ruta.id) {
|
||||
limpiarMapa(); // limpiar polylines ya dibujadas
|
||||
return;
|
||||
}
|
||||
|
||||
if (skipGuidedZoom) {
|
||||
const bounds = new google.maps.LatLngBounds()
|
||||
paradasFormateadas.forEach(p => bounds.extend(new google.maps.LatLng(p.latitud, p.longitud)))
|
||||
@ -108,7 +119,10 @@ export const useFlujoPrincipal = () => {
|
||||
await encontrarParadaCercana(ubicacion, paradas, map)
|
||||
const paradaCercanaFound = paradaCercana.value
|
||||
|
||||
if (routeStore.selectedRouteId !== _ruta.id) return;
|
||||
if (cancelToken?.cancelled || routeStore.selectedRouteId !== _ruta.id) {
|
||||
limpiarMapa();
|
||||
return;
|
||||
}
|
||||
if (!paradaCercanaFound) return;
|
||||
|
||||
// Dibujar tramo relevante
|
||||
@ -125,6 +139,12 @@ export const useFlujoPrincipal = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Guard final antes de pintar markers
|
||||
if (cancelToken?.cancelled || routeStore.selectedRouteId !== _ruta.id) {
|
||||
limpiarMapa();
|
||||
return;
|
||||
}
|
||||
|
||||
// Renderizado Condicional de Marcadores
|
||||
paradasFormateadas.forEach((p, i) => {
|
||||
const esCercana = i === idx;
|
||||
|
||||
Reference in New Issue
Block a user