diff --git a/src/ol/imagetile.js b/src/ol/imagetile.js index b440e908ad..9aae36da74 100644 --- a/src/ol/imagetile.js +++ b/src/ol/imagetile.js @@ -72,6 +72,8 @@ ol.ImageTile.prototype.disposeInternal = function() { if (this.interimTile) { this.interimTile.dispose(); } + this.state = ol.TileState.ABORT; + this.changed(); goog.base(this, 'disposeInternal'); }; diff --git a/src/ol/tile.js b/src/ol/tile.js index aa59502afc..db8dc95563 100644 --- a/src/ol/tile.js +++ b/src/ol/tile.js @@ -15,7 +15,8 @@ ol.TileState = { LOADING: 1, LOADED: 2, ERROR: 3, - EMPTY: 4 + EMPTY: 4, + ABORT: 5 }; diff --git a/src/ol/tilequeue.js b/src/ol/tilequeue.js index 62743a5f99..141f54bd6c 100644 --- a/src/ol/tilequeue.js +++ b/src/ol/tilequeue.js @@ -1,6 +1,7 @@ goog.provide('ol.TilePriorityFunction'); goog.provide('ol.TileQueue'); +goog.require('goog.asserts'); goog.require('ol.events'); goog.require('ol.events.EventType'); goog.require('ol.Coordinate'); @@ -56,7 +57,7 @@ ol.TileQueue = function(tilePriorityFunction, tileChangeCallback) { /** * @private - * @type {Object.} + * @type {!Object.} */ this.tilesLoadingKeys_ = {}; @@ -94,7 +95,7 @@ ol.TileQueue.prototype.handleTileChange = function(event) { var tile = /** @type {ol.Tile} */ (event.target); var state = tile.getState(); if (state === ol.TileState.LOADED || state === ol.TileState.ERROR || - state === ol.TileState.EMPTY) { + state === ol.TileState.EMPTY || state === ol.TileState.ABORT) { ol.events.unlisten(tile, ol.events.EventType.CHANGE, this.handleTileChange, this); var tileKey = tile.getKey(); @@ -104,6 +105,7 @@ ol.TileQueue.prototype.handleTileChange = function(event) { } this.tileChangeCallback_(); } + goog.asserts.assert(Object.keys(this.tilesLoadingKeys_).length === this.tilesLoading_); }; @@ -113,15 +115,17 @@ ol.TileQueue.prototype.handleTileChange = function(event) { */ ol.TileQueue.prototype.loadMoreTiles = function(maxTotalLoading, maxNewLoads) { var newLoads = 0; - var tile; + var tile, tileKey; while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads && this.getCount() > 0) { tile = /** @type {ol.Tile} */ (this.dequeue()[0]); - if (tile.getState() === ol.TileState.IDLE) { - this.tilesLoadingKeys_[tile.getKey()] = true; + tileKey = tile.getKey(); + if (tile.getState() === ol.TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) { + this.tilesLoadingKeys_[tileKey] = true; ++this.tilesLoading_; ++newLoads; tile.load(); } + goog.asserts.assert(Object.keys(this.tilesLoadingKeys_).length === this.tilesLoading_); } }; diff --git a/test/spec/ol/tilequeue.test.js b/test/spec/ol/tilequeue.test.js index 5d9067bd36..8a8c517292 100644 --- a/test/spec/ol/tilequeue.test.js +++ b/test/spec/ol/tilequeue.test.js @@ -14,15 +14,16 @@ describe('ol.TileQueue', function() { } var tileId = 0; - function createImageTile() { + function createImageTile(opt_tileLoadFunction) { ++tileId; var tileCoord = [tileId, tileId, tileId]; var state = ol.TileState.IDLE; var src = 'data:image/gif;base64,R0lGODlhAQABAPAAAP8AAP///' + 'yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==#' + tileId; - return new ol.ImageTile(tileCoord, state, src, null, - ol.source.Image.defaultImageLoadFunction); + var tileLoadFunction = opt_tileLoadFunction ? + opt_tileLoadFunction : ol.source.Image.defaultImageLoadFunction; + return new ol.ImageTile(tileCoord, state, src, null, tileLoadFunction); } describe('#loadMoreTiles()', function() { @@ -121,11 +122,47 @@ describe('ol.TileQueue', function() { }); }); + + describe('tile change event', function() { + var noop = function() {}; + + it('abort queued tiles', function() { + var tq = new ol.TileQueue(noop, noop); + var tile = createImageTile(); + expect(tile.hasListener(ol.events.EventType.CHANGE)).to.be(false); + + tq.enqueue([tile]); + expect(tile.hasListener(ol.events.EventType.CHANGE)).to.be(true); + + tile.dispose(); + expect(tile.hasListener(ol.events.EventType.CHANGE)).to.be(false); + expect(tile.getState()).to.eql(ol.TileState.ABORT); + }); + + it('abort loading tiles', function() { + var tq = new ol.TileQueue(noop, noop); + var tile = createImageTile(noop); + + tq.enqueue([tile]); + tq.loadMoreTiles(Infinity, Infinity); + expect(tq.getTilesLoading()).to.eql(1); + expect(tile.getState()).to.eql(ol.TileState.LOADING); + + tile.dispose(); + expect(tq.getTilesLoading()).to.eql(0); + expect(tile.hasListener(ol.events.EventType.CHANGE)).to.be(false); + expect(tile.getState()).to.eql(ol.TileState.ABORT); + + }); + + }); + }); goog.require('ol.ImageTile'); goog.require('ol.Tile'); goog.require('ol.TileState'); goog.require('ol.TileQueue'); +goog.require('ol.events.EventType'); goog.require('ol.source.Image'); goog.require('ol.structs.PriorityQueue');