modules/geo-layers/src/tile-layer/tile-2d-header.js (90 lines of code) (raw):

/* eslint-env browser */ import {log} from '@deck.gl/core'; export default class Tile2DHeader { constructor({x, y, z, onTileLoad, onTileError}) { this.x = x; this.y = y; this.z = z; this.isVisible = false; this.isSelected = false; this.parent = null; this.children = []; this.content = null; this._isLoaded = false; this._isCancelled = false; this.onTileLoad = onTileLoad; this.onTileError = onTileError; } get data() { return this._isLoaded ? this.content : this._loader; } get isLoaded() { return this._isLoaded; } get isLoading() { return Boolean(this._loader); } get isCancelled() { return this._isCancelled; } get byteLength() { const result = this.content ? this.content.byteLength : 0; if (!Number.isFinite(result)) { log.error('byteLength not defined in tile data')(); } return result; } /* eslint-disable max-statements */ async _loadData(getTileData, requestScheduler) { const {x, y, z, bbox} = this; this._abortController = new AbortController(); // eslint-disable-line no-undef const {signal} = this._abortController; const requestToken = await requestScheduler.scheduleRequest(this, tile => { return tile.isSelected ? 1 : -1; }); // A tile can be cancelled while being scheduled if (!requestToken || this._isCancelled) { this._isCancelled = true; return; } this._isCancelled = false; let tileData; let error; try { tileData = await getTileData({x, y, z, bbox, signal}); } catch (err) { error = err || true; } finally { requestToken.done(); if (this._isCancelled && !tileData) { this._isLoaded = false; } else { // Consider it loaded if we tried to cancel but `getTileData` still returned data this._isLoaded = true; this._isCancelled = false; } } if (!this._isLoaded) { return; } if (error) { this.onTileError(error, this); } else { this.content = tileData; this.onTileLoad(this); } } /* eslint-enable max-statements */ loadData(getTileData, requestScheduler) { if (!getTileData) { return; } this._isCancelled = false; this._loader = this._loadData(getTileData, requestScheduler); this._loader.finally(() => { this._loader = undefined; }); } abort() { if (this.isLoaded) { return; } this._isCancelled = true; this._abortController.abort(); } }