Cancel a view-bounded load when the camera returns to the drawn view

Moving from view A to B started B's request; moving back to A before it
finished returned early because A was already drawn, so B's request ran
on and its features replaced A's while the camera was at A. Returning to
the drawn view now cancels the request in between.
This commit is contained in:
Sameh Khamis committed 2026-11-12 15:49:56 -08:00
1 parent 0f13c0a1c2
commit 7d91a1875b
2 files changed
+51 -1

No files matched your search

+10 -1
View File
@@ -753,7 +753,16 @@ export function createLibraryViewLayer(
const box = viewBox(height);
if (!box) return;
const key = box.map((value) => value.toFixed(4)).join(',');
if (key === loadedKey && dataSource) return;
// Back on the view already drawn: a request for the view in between is
// obsolete and must not replace it.
if (key === loadedKey && dataSource) {
if (controller) {
abort();
loading = false;
render();
}
return;
}
abort();
const current = new AbortController();
controller = current;
+41
View File
@@ -116,6 +116,47 @@ test('below it, the layer loads the box around the view centre and reads PARTIAL
assert.equal(added.length, 0);
});
test('returning to the drawn view cancels the request for the view in between', async () => {
let release;
const signals = [];
let call = 0;
const layer = createLibraryViewLayer(entry, {
source: {
loadDataset: async (target, { signal }) => {
signals.push(signal);
call += 1;
if (call === 2)
await new Promise((resolve) => {
release = resolve;
});
return { features: [polygon], truncated: false };
},
},
cesium: fakeCesium,
});
const { viewer, added } = fakeViewer({ height: 2000 });
const moveTo = (lon, lat) => {
viewer.camera.positionWC = Cesium.Cartesian3.fromDegrees(lon, lat, 2000);
viewer.camera.pickEllipsoid = () => Cesium.Cartesian3.fromDegrees(lon, lat, 0);
viewer.camera.computeViewRectangle = () =>
Cesium.Rectangle.fromDegrees(lon - 1, lat - 1, lon + 1, lat + 1);
};
await layer.init(viewer);
await layer.enable(viewer);
const drawn = added[0];
moveTo(-77.2, 38.95);
const between = layer.enable(viewer);
await new Promise((resolve) => setImmediate(resolve));
moveTo(-77.03, 38.89);
await layer.enable(viewer);
assert.equal(signals[1].aborted, true);
release();
await between;
assert.deepEqual(added, [drawn]);
assert.equal(layer.getStats().loading, false);
await layer.destroy(viewer);
});
test('the row legend labels each colour and counts what is in view', async () => {
const { colorByLegend } = await import('./layers.js');
const bridges = libraryEntry('ntad-national-bridges');