Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cancel pending requests on map.remove() #6826

Merged
merged 1 commit into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions bench/lib/create_map.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import Map from '../../src/ui/map';

import browser from '../../src/util/browser';

export default function (options: any): Promise<Map> {
return new Promise((resolve, reject) => {
const container = document.createElement('div');
Expand All @@ -24,9 +22,9 @@ export default function (options: any): Promise<Map> {
map._rerender = () => {};

// If there's a pending rerender, cancel it.
if (map._frameId) {
browser.cancelFrame(map._frameId);
map._frameId = null;
if (map._frame) {
map._frame.cancel();
map._frame = null;
}

resolve(map);
Expand Down
7 changes: 4 additions & 3 deletions src/source/load_tilejson.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import { normalizeSourceURL as normalizeURL } from '../util/mapbox';
import type {RequestTransformFunction} from '../ui/map';
import type {Callback} from '../types/callback';
import type {TileJSON} from '../types/tilejson';
import type {Cancelable} from '../types/cancelable';

export default function(options: any, requestTransformFn: RequestTransformFunction, callback: Callback<TileJSON>) {
export default function(options: any, requestTransformFn: RequestTransformFunction, callback: Callback<TileJSON>): Cancelable {
const loaded = function(err, tileJSON: any) {
if (err) {
return callback(err);
Expand All @@ -30,8 +31,8 @@ export default function(options: any, requestTransformFn: RequestTransformFuncti
};

if (options.url) {
getJSON(requestTransformFn(normalizeURL(options.url), ResourceType.Source), loaded);
return getJSON(requestTransformFn(normalizeURL(options.url), ResourceType.Source), loaded);
} else {
browser.frame(() => loaded(null, options));
return browser.frame(() => loaded(null, options));
}
}
14 changes: 12 additions & 2 deletions src/source/raster_tile_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type Map from '../ui/map';
import type Dispatcher from '../util/dispatcher';
import type Tile from './tile';
import type {Callback} from '../types/callback';
import type {Cancelable} from '../types/cancelable';

class RasterTileSource extends Evented implements Source {
type: 'raster' | 'raster-dem';
Expand All @@ -34,6 +35,7 @@ class RasterTileSource extends Evented implements Source {

_loaded: boolean;
_options: RasterSourceSpecification | RasterDEMSourceSpecification;
_tileJSONRequest: ?Cancelable;

constructor(id: string, options: RasterSourceSpecification | RasterDEMSourceSpecification, dispatcher: Dispatcher, eventedParent: Evented) {
super();
Expand All @@ -55,7 +57,8 @@ class RasterTileSource extends Evented implements Source {

load() {
this.fire(new Event('dataloading', {dataType: 'source'}));
loadTileJSON(this._options, this.map._transformRequest, (err, tileJSON) => {
this._tileJSONRequest = loadTileJSON(this._options, this.map._transformRequest, (err, tileJSON) => {
this._tileJSONRequest = null;
if (err) {
this.fire(new ErrorEvent(err));
} else if (tileJSON) {
Expand All @@ -76,6 +79,13 @@ class RasterTileSource extends Evented implements Source {
this.load();
}

onRemove() {
if (this._tileJSONRequest) {
this._tileJSONRequest.cancel();
this._tileJSONRequest = null;
}
}

serialize() {
return extend({}, this._options);
}
Expand Down Expand Up @@ -123,7 +133,7 @@ class RasterTileSource extends Evented implements Source {

abortTile(tile: Tile, callback: Callback<void>) {
if (tile.request) {
tile.request.abort();
tile.request.cancel();
delete tile.request;
}
callback();
Expand Down
5 changes: 3 additions & 2 deletions src/source/tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type Framebuffer from '../gl/framebuffer';
import type {PerformanceResourceTiming} from '../types/performance_resource_timing';
import type Transform from '../geo/transform';
import type {LayerFeatureStates} from './source_state';
import type {Cancelable} from '../types/cancelable';

export type TileState =
| 'loading' // Tile data is in the process of loading.
Expand Down Expand Up @@ -80,8 +81,8 @@ class Tile {
maskedBoundsBuffer: ?VertexBuffer;
maskedIndexBuffer: ?IndexBuffer;
segments: ?SegmentVector;
needsHillshadePrepare: ?boolean
request: any;
needsHillshadePrepare: ?boolean;
request: ?Cancelable;
texture: any;
fbo: ?Framebuffer;
demTexture: ?Texture;
Expand Down
13 changes: 11 additions & 2 deletions src/source/vector_tile_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type Map from '../ui/map';
import type Dispatcher from '../util/dispatcher';
import type Tile from './tile';
import type {Callback} from '../types/callback';
import type {Cancelable} from '../types/cancelable';

class VectorTileSource extends Evented implements Source {
type: 'vector';
Expand All @@ -34,6 +35,7 @@ class VectorTileSource extends Evented implements Source {
tileBounds: TileBounds;
reparseOverscaled: boolean;
isTileClipped: boolean;
_tileJSONRequest: ?Cancelable;

constructor(id: string, options: VectorSourceSpecification & {collectResourceTiming: boolean}, dispatcher: Dispatcher, eventedParent: Evented) {
super();
Expand Down Expand Up @@ -62,8 +64,8 @@ class VectorTileSource extends Evented implements Source {

load() {
this.fire(new Event('dataloading', {dataType: 'source'}));

loadTileJSON(this._options, this.map._transformRequest, (err, tileJSON) => {
this._tileJSONRequest = loadTileJSON(this._options, this.map._transformRequest, (err, tileJSON) => {
this._tileJSONRequest = null;
if (err) {
this.fire(new ErrorEvent(err));
} else if (tileJSON) {
Expand All @@ -88,6 +90,13 @@ class VectorTileSource extends Evented implements Source {
this.load();
}

onRemove() {
if (this._tileJSONRequest) {
this._tileJSONRequest.cancel();
this._tileJSONRequest = null;
}
}

serialize() {
return extend({}, this._options);
}
Expand Down
4 changes: 2 additions & 2 deletions src/source/vector_tile_worker_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type LoadVectorData = (params: WorkerTileParameters, callback: LoadVector
* @private
*/
function loadVectorTile(params: WorkerTileParameters, callback: LoadVectorDataCallback) {
const xhr = getArrayBuffer(params.request, (err, response) => {
const request = getArrayBuffer(params.request, (err, response) => {
if (err) {
callback(err);
} else if (response) {
Expand All @@ -56,7 +56,7 @@ function loadVectorTile(params: WorkerTileParameters, callback: LoadVectorDataCa
}
});
return () => {
xhr.abort();
request.cancel();
callback();
};
}
Expand Down
22 changes: 19 additions & 3 deletions src/style/load_sprite.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,25 @@ import { RGBAImage } from '../util/image';
import type {StyleImage} from './style_image';
import type {RequestTransformFunction} from '../ui/map';
import type {Callback} from '../types/callback';
import type {Cancelable} from '../types/cancelable';

export default function(baseURL: string,
transformRequestCallback: RequestTransformFunction,
callback: Callback<{[string]: StyleImage}>) {
callback: Callback<{[string]: StyleImage}>): Cancelable {
let json: any, image, error;
const format = browser.devicePixelRatio > 1 ? '@2x' : '';

getJSON(transformRequestCallback(normalizeSpriteURL(baseURL, format, '.json'), ResourceType.SpriteJSON), (err, data) => {
let jsonRequest = getJSON(transformRequestCallback(normalizeSpriteURL(baseURL, format, '.json'), ResourceType.SpriteJSON), (err, data) => {
jsonRequest = null;
if (!error) {
error = err;
json = data;
maybeComplete();
}
});

getImage(transformRequestCallback(normalizeSpriteURL(baseURL, format, '.png'), ResourceType.SpriteImage), (err, img) => {
let imageRequest = getImage(transformRequestCallback(normalizeSpriteURL(baseURL, format, '.png'), ResourceType.SpriteImage), (err, img) => {
imageRequest = null;
if (!error) {
error = err;
image = img;
Expand All @@ -49,4 +52,17 @@ export default function(baseURL: string,
callback(null, result);
}
}

return {
cancel() {
if (jsonRequest) {
jsonRequest.cancel();
jsonRequest = null;
}
if (imageRequest) {
imageRequest.cancel();
imageRequest = null;
}
}
};
}
22 changes: 18 additions & 4 deletions src/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ import type {StyleImage} from './style_image';
import type {StyleGlyph} from './style_glyph';
import type {Callback} from '../types/callback';
import type EvaluationParameters from './evaluation_parameters';
import type { Placement } from '../symbol/placement';
import type {Placement} from '../symbol/placement';
import type {Cancelable} from '../types/cancelable';

const supportedDiffOperations = pick(diffOperations, [
'addLayer',
Expand Down Expand Up @@ -90,6 +91,8 @@ class Style extends Evented {
lineAtlas: LineAtlas;
light: Light;

_request: ?Cancelable;
_spriteRequest: ?Cancelable;
_layers: {[string]: StyleLayer};
_order: Array<string>;
sourceCaches: {[string]: SourceCache};
Expand Down Expand Up @@ -175,7 +178,8 @@ class Style extends Evented {
url = normalizeStyleURL(url, options.accessToken);
const request = this.map._transformRequest(url, ResourceType.Style);

getJSON(request, (error, json) => {
this._request = getJSON(request, (error, json) => {
this._request = null;
if (error) {
this.fire(new ErrorEvent(error));
} else if (json) {
Expand All @@ -189,7 +193,8 @@ class Style extends Evented {
} = {}) {
this.fire(new Event('dataloading', {dataType: 'style'}));

browser.frame(() => {
this._request = browser.frame(() => {
this._request = null;
this._load(json, options.validate !== false);
});
}
Expand All @@ -207,7 +212,8 @@ class Style extends Evented {
}

if (json.sprite) {
loadSprite(json.sprite, this.map._transformRequest, (err, images) => {
this._spriteRequest = loadSprite(json.sprite, this.map._transformRequest, (err, images) => {
this._spriteRequest = null;
if (err) {
this.fire(new ErrorEvent(err));
} else if (images) {
Expand Down Expand Up @@ -976,6 +982,14 @@ class Style extends Evented {
}

_remove() {
if (this._request) {
this._request.cancel();
this._request = null;
}
if (this._spriteRequest) {
this._spriteRequest.cancel();
this._spriteRequest = null;
}
rtlTextPluginEvented.off('pluginAvailable', this._rtlTextPluginCallback);
for (const id in this.sourceCaches) {
this.sourceCaches[id].clearTiles();
Expand Down
3 changes: 3 additions & 0 deletions src/types/cancelable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @flow

export type Cancelable = { cancel: () => void };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too bad there isn't something like Rust's must_use attribute

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

21 changes: 12 additions & 9 deletions src/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import type KeyboardHandler from './handler/keyboard';
import type DoubleClickZoomHandler from './handler/dblclick_zoom';
import type TouchZoomRotateHandler from './handler/touch_zoom_rotate';
import type {TaskID} from '../util/task_queue';
import type {Cancelable} from '../types/cancelable';

type ControlPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';

Expand Down Expand Up @@ -237,7 +238,7 @@ class Map extends Camera {
_canvas: HTMLCanvasElement;
_transformRequest: RequestTransformFunction;
_maxTileCacheSize: number;
_frameId: any;
_frame: ?Cancelable;
_styleDirty: ?boolean;
_sourcesDirty: ?boolean;
_placementDirty: ?boolean;
Expand Down Expand Up @@ -1546,9 +1547,9 @@ class Map extends Camera {

_contextLost(event: *) {
event.preventDefault();
if (this._frameId) {
browser.cancelFrame(this._frameId);
this._frameId = null;
if (this._frame) {
this._frame.cancel();
this._frame = null;
}
this.fire(new Event('webglcontextlost', {originalEvent: event}));
}
Expand Down Expand Up @@ -1703,9 +1704,11 @@ class Map extends Camera {
*/
remove() {
if (this._hash) this._hash.remove();
browser.cancelFrame(this._frameId);
if (this._frame) {
this._frame.cancel();
this._frame = null;
}
this._renderTaskQueue.clear();
this._frameId = null;
this.setStyle(null);
if (typeof window !== 'undefined') {
window.removeEventListener('resize', this._onWindowResize, false);
Expand All @@ -1721,9 +1724,9 @@ class Map extends Camera {
}

_rerender() {
if (this.style && !this._frameId) {
this._frameId = browser.frame(() => {
this._frameId = null;
if (this.style && !this._frame) {
this._frame = browser.frame(() => {
this._frame = null;
this._render();
});
}
Expand Down
Loading