perf(monitor): throttle selected address lookups

This commit is contained in:
lingniu
2026-07-16 05:52:29 +08:00
parent 3f7619c7cd
commit 4302fc8d45
3 changed files with 121 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { cleanup, render, renderHook, waitFor } from '@testing-library/react';
import { act, cleanup, render, renderHook, waitFor } from '@testing-library/react';
import { afterEach, expect, test, vi } from 'vitest';
import type { ReactNode } from 'react';
import { api } from '../../api/client';
@@ -7,6 +7,7 @@ import { useMonitorData, useMonitorVehicleCard } from './useMonitorData';
afterEach(() => {
cleanup();
vi.useRealTimers();
vi.restoreAllMocks();
});
@@ -126,3 +127,47 @@ test('collapsed vehicle card does not issue or retain detail-only queries', asyn
view.unmount();
client.clear();
});
test('throttles moving vehicle address lookups, publishes the latest point, and switches vehicles immediately', async () => {
vi.useFakeTimers();
vi.spyOn(api, 'vehicleDetail').mockResolvedValue({} as never);
vi.spyOn(api, 'alertEventsV2').mockResolvedValue({ items: [], total: 0, limit: 20, offset: 0 });
const address = vi.spyOn(api, 'reverseGeocode').mockResolvedValue({ provider: 'AMap', longitude: 113.26, latitude: 23.13, formattedAddress: '测试地址' });
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
function ActiveCard({ vehicle }: { vehicle: { vin: string; longitude: number; latitude: number } }) {
useMonitorVehicleCard(vehicle.vin, vehicle as never, true);
return null;
}
const view = render(<QueryClientProvider client={client}><ActiveCard vehicle={{ vin: 'VIN-001', longitude: 113.260041, latitude: 23.130041 }} /></QueryClientProvider>);
await act(async () => { await Promise.resolve(); await Promise.resolve(); });
expect(address).toHaveBeenCalledTimes(1);
expect(address.mock.calls[0]?.[0]?.get('longitude')).toBe('113.2600');
expect(address.mock.calls[0]?.[0]?.get('latitude')).toBe('23.1300');
view.rerender(<QueryClientProvider client={client}><ActiveCard vehicle={{ vin: 'VIN-001', longitude: 113.260049, latitude: 23.130049 }} /></QueryClientProvider>);
await act(async () => { await Promise.resolve(); });
expect(address).toHaveBeenCalledTimes(1);
view.rerender(<QueryClientProvider client={client}><ActiveCard vehicle={{ vin: 'VIN-001', longitude: 113.270041, latitude: 23.140041 }} /></QueryClientProvider>);
await act(async () => { vi.advanceTimersByTime(30_000); await Promise.resolve(); });
view.rerender(<QueryClientProvider client={client}><ActiveCard vehicle={{ vin: 'VIN-001', longitude: 113.280041, latitude: 23.150041 }} /></QueryClientProvider>);
await act(async () => { vi.advanceTimersByTime(29_999); await Promise.resolve(); });
expect(address).toHaveBeenCalledTimes(1);
await act(async () => { vi.advanceTimersByTime(1); await Promise.resolve(); await Promise.resolve(); });
expect(address).toHaveBeenCalledTimes(2);
expect(address.mock.calls[1]?.[0]?.get('longitude')).toBe('113.2800');
expect(address.mock.calls[1]?.[0]?.get('latitude')).toBe('23.1500');
view.rerender(<QueryClientProvider client={client}><ActiveCard vehicle={{ vin: 'VIN-002', longitude: 114.310041, latitude: 22.910041 }} /></QueryClientProvider>);
await act(async () => { await Promise.resolve(); await Promise.resolve(); });
expect(address).toHaveBeenCalledTimes(3);
expect(address.mock.calls[2]?.[0]?.get('longitude')).toBe('114.3100');
view.rerender(<QueryClientProvider client={client}><ActiveCard vehicle={{ vin: 'VIN-002', longitude: 114.320041, latitude: 22.920041 }} /></QueryClientProvider>);
view.unmount();
await act(async () => { vi.advanceTimersByTime(60_000); await Promise.resolve(); });
expect(address).toHaveBeenCalledTimes(3);
client.clear();
});