mirror of
https://github.com/openseadragon/openseadragon.git
synced 2025-03-14 04:56:19 +03:00
Feature/Optimization: cache can be created by a callback (async or sync), to avoid premature data creation
This commit is contained in:
parent
b6693ee50d
commit
f8e5cff117
64
src/tile.js
64
src/tile.js
@ -423,8 +423,9 @@ $.Tile.prototype = {
|
||||
* @deprecated
|
||||
*/
|
||||
set context2D(value) {
|
||||
$.console.error("[Tile.context2D] property has been deprecated. Use [Tile.setData] instead.");
|
||||
$.console.error("[Tile.context2D] property has been deprecated. Use [Tile.setData] within dedicated update event instead.");
|
||||
this.setData(value, "context2d");
|
||||
this.updateRenderTarget();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -473,26 +474,7 @@ $.Tile.prototype = {
|
||||
if (!this.tiledImage) {
|
||||
return $.Promise.resolve(); //async can access outside its lifetime
|
||||
}
|
||||
|
||||
$.console.assert("TIle.getData requires type argument! got '%s'.", type);
|
||||
|
||||
//we return the data synchronously immediatelly (undefined if conversion happens)
|
||||
const cache = this.getCache(this._wcKey);
|
||||
if (!cache) {
|
||||
const targetCopyKey = this.__restore ? this.originalCacheKey : this.cacheKey;
|
||||
const origCache = this.getCache(targetCopyKey);
|
||||
if (!origCache) {
|
||||
$.console.error("[Tile::getData] There is no cache available for tile with key %s", targetCopyKey);
|
||||
}
|
||||
|
||||
//todo consider calling addCache with callback, which can avoid creating data item only to just discard it
|
||||
// in case we addCache with existing key and the current tile just gets attached as a reference
|
||||
// .. or explicitly check that such cache does not exist globally (now checking only locally)
|
||||
return origCache.getDataAs(type, true).then(data => {
|
||||
return this.addCache(this._wcKey, data, type, false, false).await();
|
||||
});
|
||||
}
|
||||
return cache.getDataAs(type, false);
|
||||
return this._getOrCreateWorkingCacheData(type);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -521,10 +503,10 @@ $.Tile.prototype = {
|
||||
return null; //async context can access the tile outside its lifetime
|
||||
}
|
||||
|
||||
const cache = this.getCache(this._wcKey);
|
||||
let cache = this.getCache(this._wcKey);
|
||||
if (!cache) {
|
||||
$.console.error("[Tile::setData] You cannot set data without calling tile.getData()! The working cache is not initialized!");
|
||||
return $.Promise.resolve();
|
||||
this._getOrCreateWorkingCacheData(undefined);
|
||||
cache = this.getCache(this._wcKey);
|
||||
}
|
||||
return cache.setDataAs(value, type);
|
||||
},
|
||||
@ -611,8 +593,11 @@ $.Tile.prototype = {
|
||||
* @param {string} key cache key, must be unique (we recommend re-using this.cacheTile
|
||||
* value and extend it with some another unique content, by default overrides the existing
|
||||
* main cache used for drawing, if not existing.
|
||||
* @param {*} data data to cache - this data will be IGNORED if cache already exists!
|
||||
* @param {string} [type=undefined] data type, will be guessed if not provided
|
||||
* @param {*} data this data will be IGNORED if cache already exists; therefore if
|
||||
* `typeof data === 'function'` holds (both async and normal functions), the data is called to obtain
|
||||
* the data item: this is an optimization to load data only when necessary.
|
||||
* @param {string} [type=undefined] data type, will be guessed if not provided (not recommended),
|
||||
* if data is a callback the type is a mandatory field, not setting it results in undefined behaviour
|
||||
* @param {boolean} [setAsMain=false] if true, the key will be set as the tile.cacheKey
|
||||
* @param [_safely=true] private
|
||||
* @returns {OpenSeadragon.CacheRecord|null} - The cache record the tile was attached to.
|
||||
@ -628,6 +613,9 @@ $.Tile.prototype = {
|
||||
"Automated deduction is potentially unsafe: prefer specification of data type explicitly.");
|
||||
this.__typeWarningReported = true;
|
||||
}
|
||||
if (typeof data === 'function') {
|
||||
$.console.error("[TileCache.cacheTile] options.data as a callback requires type argument! Current is " + type);
|
||||
}
|
||||
type = $.convertor.guessType(data);
|
||||
}
|
||||
|
||||
@ -677,6 +665,30 @@ $.Tile.prototype = {
|
||||
// as drawers request data for drawing
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes working cache if it does not exist.
|
||||
* @param {string|undefined} type initial cache type to create
|
||||
* @return {OpenSeadragon.Promise<?>} data-awaiting promise with the cache data
|
||||
* @private
|
||||
*/
|
||||
_getOrCreateWorkingCacheData: function (type) {
|
||||
const cache = this.getCache(this._wcKey);
|
||||
if (!cache) {
|
||||
const targetCopyKey = this.__restore ? this.originalCacheKey : this.cacheKey;
|
||||
const origCache = this.getCache(targetCopyKey);
|
||||
if (!origCache) {
|
||||
$.console.error("[Tile::getData] There is no cache available for tile with key %s", targetCopyKey);
|
||||
}
|
||||
// Here ensure type is defined, rquired by data callbacks
|
||||
type = type || origCache.type;
|
||||
|
||||
// Here we use extensively ability to call addCache with callback: working cache is created only if not
|
||||
// already in memory (=> shared).
|
||||
return this.addCache(this._wcKey, () => origCache.getDataAs(type, true), type, false, false).await();
|
||||
}
|
||||
return cache.getDataAs(type, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of caches available to this tile
|
||||
* @returns {number} number of caches
|
||||
|
@ -75,7 +75,7 @@
|
||||
|
||||
/**
|
||||
* Await ongoing process so that we get cache ready on callback.
|
||||
* @returns {Promise<any>}
|
||||
* @returns {OpenSeadragon.Promise<?>}
|
||||
*/
|
||||
await() {
|
||||
if (!this._promise) { //if not cache loaded, do not fail
|
||||
@ -403,9 +403,24 @@
|
||||
|
||||
// first come first served, data for existing tiles is NOT overridden
|
||||
if (this._tiles.length < 1) {
|
||||
// Since we IGNORE new data if already initialized, we support 'data getter'
|
||||
if (typeof data === 'function') {
|
||||
data = data();
|
||||
}
|
||||
|
||||
// If we receive async callback, we consume the async state
|
||||
if (data instanceof $.Promise) {
|
||||
this._promise = data.then(d => {
|
||||
this._data = d;
|
||||
return d;
|
||||
});
|
||||
this._data = null;
|
||||
} else {
|
||||
this._promise = $.Promise.resolve(data);
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
this._type = type;
|
||||
this._promise = $.Promise.resolve(data);
|
||||
this._data = data;
|
||||
this.loaded = true;
|
||||
this._tiles.push(tile);
|
||||
} else if (!this._tiles.includes(tile)) {
|
||||
@ -734,7 +749,8 @@
|
||||
* @param {String} options.tile.cacheKey - The unique key used to identify this tile in the cache.
|
||||
* Used if options.cacheKey not set.
|
||||
* @param {Image} options.image - The image of the tile to cache. Deprecated.
|
||||
* @param {*} options.data - The data of the tile to cache.
|
||||
* @param {*} options.data - The data of the tile to cache. If `typeof data === 'function'` holds,
|
||||
* the data is called to obtain the data item: this is an optimization to load data only when necessary.
|
||||
* @param {string} [options.dataType] - The data type of the tile to cache. Required.
|
||||
* @param {Number} [options.cutoff=0] - If adding this tile goes over the cache max count, this
|
||||
* function will release an old tile. The cutoff option specifies a tile level at or below which
|
||||
@ -777,6 +793,12 @@
|
||||
if (!options.dataType) {
|
||||
$.console.error("[TileCache.cacheTile] options.dataType is newly required. " +
|
||||
"For easier use of the cache system, use the tile instance API.");
|
||||
|
||||
// We need to force data acquisition now to guess the type
|
||||
if (typeof options.data === 'function') {
|
||||
$.console.error("[TileCache.cacheTile] options.dataType is mandatory " +
|
||||
" when data item is a callback!");
|
||||
}
|
||||
options.dataType = $.convertor.guessType(options.data);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user