@dasch-swiss/dsp-js
Version:
JavaScript library that handles API requests to Knora
120 lines • 4.91 kB
JavaScript
import { of } from "rxjs";
import { map, shareReplay, take, tap } from "rxjs";
/**
* Generic cache class.
* Fetches information of a specific type from Knora once and caches it.
* Fetches also dependencies of a requested element (non-blocking).
* Works also with multiple async requests for the same key, also if not cached yet.
*
* @category Internal
*/
var GenericCache = /** @class */ (function () {
function GenericCache() {
/**
* Cache object: key -> value.
*/
this.cache = {};
}
/**
* Gets a specific item from the cache.
* If not cached yet, the information will be retrieved from DSP-API.
*
* @param key the id of the item to be returned.
* @param isDependency true if the item to be returned
* is a dependency of another item (recursive call to this method).
*/
GenericCache.prototype.getItem = function (key, isDependency) {
var _this = this;
if (isDependency === void 0) { isDependency = false; }
// If the key already exists,
// return the associated Observable.
if (this.cache[key] !== undefined) {
return this.cache[key];
}
// store the observable in the cache
// the next request for the same key will immediately get the observable
// also if the request has not finished yet
this.cache[key] = this.requestItemFromKnora(key, isDependency).pipe(
// only one item is expected
take(1),
// DSP-API may return several elements for the request (optimization)
tap(function (items) {
if (items.length === 0)
throw Error("No items returned from DSP-API for ".concat(key));
// the first item is expected to be the requested item
if (key !== _this.getKeyOfItem(items[0]))
throw Error("First item of items returned from DSP-API is expected to be {$key}");
// save all additional items returned for this request
_this.saveAdditionalItems(items.slice(1));
// request dependencies of all items
_this.requestDependencies(items);
}),
// only write the requested item to the cache for the given key
map(function (res) { return res[0]; }),
// make it a `ReplaySubject` so that all subscribers
// will get the latest and only emitted value
//
// side effects (dependency handling, optimization) will only be performed once
//
// failed observables will be retried upon the next subscription
shareReplay({ refCount: false, bufferSize: 1 }));
// return the observable immediately (sync)
return this.cache[key];
};
/**
* Deletes an existing entry in the cache and requests information from DSP-API.
*
* @param key the id of the information to be returned.
* @return the item.
*/
GenericCache.prototype.reloadItem = function (key) {
if (this.cache[key] !== undefined)
delete this.cache[key];
return this.getItem(key);
};
/**
* Handle additional items that were resolved with a request.
*
* @param items dependencies that have been retrieved.
*/
GenericCache.prototype.saveAdditionalItems = function (items) {
var _this = this;
// Write all available items to the cache (only for non existing keys)
// Analyze dependencies of available items.
items.forEach(function (item) {
// Get key of item
var itemKey = _this.getKeyOfItem(item);
// Only write an additional item to the cache
// if there is not entry for it yet
// item for `key` has already been handled
if (_this.cache[itemKey] === undefined) {
_this.cache[itemKey] = of(item);
}
});
};
/**
* Requests dependencies of the items retrieved from DSP-API.
*
* @param items items returned from DSP-API to a request.
*/
GenericCache.prototype.requestDependencies = function (items) {
var _this = this;
items.forEach(function (item) {
// get items this item depends on
_this.getDependenciesOfItem(item)
.filter(function (depKey) {
// ignore dependencies already taken care of
return Object.keys(_this.cache).indexOf(depKey) === -1;
})
.forEach(function (depKey) {
// Request each dependency from the cache
// Dependencies will be fetched independently (non-blocking).
// Subscribe because the Observable is lazy
_this.getItem(depKey, true).subscribe();
});
});
};
return GenericCache;
}());
export { GenericCache };
//# sourceMappingURL=GenericCache.js.map