transitory
Version:
In-memory cache with high hit rates via LFU eviction. Supports time-based expiration, automatic loading and metrics.
85 lines • 3.33 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultLoadingCache = void 0;
var WrappedCache_1 = require("../WrappedCache");
var DATA = Symbol('loadingData');
/**
* Extension to another cache that will load items if they are not cached.
*/
var DefaultLoadingCache = /** @class */ (function (_super) {
__extends(DefaultLoadingCache, _super);
function DefaultLoadingCache(options) {
var _this = _super.call(this, options.parent, options.removalListener || null) || this;
_this[DATA] = {
promises: new Map(),
loader: options.loader || null
};
return _this;
}
/**
* Get cached value or load it if not currently cached. Updates the usage
* of the key.
*
* @param key -
* key to get
* @param loader -
* optional loader to use for loading the object
* @returns
* promise that resolves to the loaded value
*/
DefaultLoadingCache.prototype.get = function (key, loader) {
var _this = this;
var currentValue = this.getIfPresent(key);
if (currentValue !== null) {
return Promise.resolve(currentValue);
}
var data = this[DATA];
// First check if we are already loading this value
var promise = data.promises.get(key);
if (promise)
return promise;
// Create the initial promise if we are not already loading
if (typeof loader !== 'undefined') {
if (typeof loader !== 'function') {
throw new Error('If loader is used it must be a function that returns a value or a Promise');
}
promise = Promise.resolve(loader(key));
}
else if (data.loader) {
promise = Promise.resolve(data.loader(key));
}
if (!promise) {
throw new Error('No way to load data for key: ' + key);
}
// Enhance with handler that will remove promise and set value if success
var resolve = function () { return data.promises.delete(key); };
promise = promise.then(function (result) {
_this.set(key, result);
resolve();
return result;
}).catch(function (err) {
resolve();
throw err;
});
data.promises.set(key, promise);
return promise;
};
return DefaultLoadingCache;
}(WrappedCache_1.WrappedCache));
exports.DefaultLoadingCache = DefaultLoadingCache;
//# sourceMappingURL=DefaultLoadingCache.js.map