cache2
Version:
一个简单的 JavaScript 缓存管理,支持浏览器端和 node 端。
448 lines (432 loc) • 17.7 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.cache2 = {}));
})(this, (function (exports) { 'use strict';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
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);
};
function __extends(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 __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
var EmitterPro = (function () {
function EmitterPro() {
this.handlers = {};
}
EmitterPro.prototype.eventNames = function () {
var _a;
var symbols = ((_a = Object.getOwnPropertySymbols) === null || _a === void 0 ? void 0 : _a.call(Object, this.handlers)) || [];
var keys = Object.keys(this.handlers);
return keys.concat(symbols);
};
EmitterPro.prototype.rawListeners = function (eventName) {
var handler = this.handlers[eventName];
return handler ? handler.map(function (item) { return item.raw; }) : [];
};
EmitterPro.prototype.listeners = function (eventName) {
var handler = this.handlers[eventName];
return handler ? handler.map(function (item) { return item.wrap; }) : [];
};
EmitterPro.prototype.hasListener = function (eventName, listener) {
return this.rawListeners(eventName).some(function (item) { return item === listener; });
};
EmitterPro.prototype._on = function (eventName, raw, wrap, context, dir) {
if (context === void 0) { context = null; }
if (dir === void 0) { dir = 1; }
var currentListener = { raw: raw, wrap: wrap, context: context };
if (!this.handlers[eventName]) {
this.handlers[eventName] = [currentListener];
}
else {
var appendMethod = dir === 1 ? 'push' : 'unshift';
this.handlers[eventName][appendMethod](currentListener);
}
return this;
};
EmitterPro.prototype.prependListener = function (eventName, listener, context) {
return this._on(eventName, listener, listener, context, 0);
};
EmitterPro.prototype.on = function (eventName, listener, context) {
return this._on(eventName, listener, listener, context);
};
EmitterPro.prototype._wrapOnce = function (eventName, listener, context) {
var _this = this;
if (context === void 0) { context = null; }
var wrap = (function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
listener.apply(context, args);
_this.off(eventName, wrap);
});
return wrap;
};
EmitterPro.prototype.once = function (eventName, listener, context) {
var wrap = this._wrapOnce(eventName, listener, context);
return this._on(eventName, listener, wrap, context);
};
EmitterPro.prototype.prependOnceListener = function (eventName, listener, context) {
var wrap = this._wrapOnce(eventName, listener, context);
return this._on(eventName, listener, wrap, context, 0);
};
EmitterPro.prototype.off = function (eventName, listener) {
var handler = this.handlers[eventName];
if (handler) {
if (listener) {
var index = handler.findIndex(function (item) { return item.wrap === listener || item.raw === listener; });
if (index !== -1) {
handler.splice(index, 1);
}
}
else {
delete this.handlers[eventName];
}
}
return this;
};
EmitterPro.prototype.offAll = function () {
this.handlers = {};
return this;
};
EmitterPro.prototype.emit = function (eventName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var handler = this.handlers[eventName];
if (handler && handler.length > 0) {
handler.forEach(function (listener) {
listener.wrap.apply(listener.context, args);
});
return true;
}
return false;
};
return EmitterPro;
}());
var cache = {};
var MemoryStorage = (function () {
function MemoryStorage(scope) {
if (scope === void 0) { scope = 'default'; }
this.scope = scope;
if (!cache[this.scope]) {
cache[this.scope] = {};
}
this.data = cache[this.scope];
}
MemoryStorage.prototype.getItem = function (key) {
return key in this.data ? this.data[key] : null;
};
MemoryStorage.prototype.setItem = function (key, value) {
this.data[key] = value;
};
MemoryStorage.prototype.removeItem = function (key) {
delete this.data[key];
};
MemoryStorage.prototype.clear = function () {
cache[this.scope] = {};
this.data = cache[this.scope];
};
return MemoryStorage;
}());
function randomString() {
return Math.random().toString(16).substring(2, 8);
}
function isStorageSupported(storage) {
try {
var isSupport = typeof storage === 'object' &&
storage !== null &&
!!storage.setItem &&
!!storage.getItem &&
!!storage.removeItem;
if (isSupport) {
var key = randomString() + new Date().getTime();
var value = '1';
storage.setItem(key, value);
if (storage.getItem(key) !== value) {
return false;
}
storage.removeItem(key);
}
return isSupport;
}
catch (err) {
console.error("[cache2] ".concat(storage, " is not supported. The default memory cache will be used."));
return false;
}
}
function parse(value, reviver) {
try {
return JSON.parse(value, reviver);
}
catch (err) {
return value;
}
}
function stringify(value, replacer) {
return JSON.stringify(value, replacer);
}
var Storage = (function () {
function Storage(storage, options) {
if (options === void 0) { options = {}; }
var isSupported = storage ? isStorageSupported(storage) : false;
this.options = __assign({ needParsed: isSupported, prefix: '' }, options);
this.storage = isSupported ? storage : new MemoryStorage(this.options.memoryScope);
}
Storage.prototype.getKey = function (key) {
return this.options.prefix + key;
};
Storage.prototype.get = function (key) {
var value = this.storage.getItem(this.getKey(key));
return this.options.needParsed ? parse(value, this.options.reviver) : value;
};
Storage.prototype.set = function (key, value) {
this.storage.setItem(this.getKey(key), this.options.needParsed ? stringify(value, this.options.replacer) : value);
};
Storage.prototype.del = function (key) {
this.storage.removeItem(this.getKey(key));
};
Storage.prototype.clear = function () {
if (typeof this.storage.clear === 'function') {
this.storage.clear();
}
};
return Storage;
}());
var defaultPrefix = 'cache2_';
var defaultNamespace = 'default';
var Cache = (function (_super) {
__extends(Cache, _super);
function Cache(namespace, options) {
var _this = _super.call(this) || this;
var ns = defaultNamespace, opts;
if (typeof namespace === 'string') {
ns = namespace || defaultNamespace;
}
else if (typeof namespace === 'object') {
opts = namespace;
}
if (!opts && typeof options === 'object') {
opts = options;
}
_this.options = __assign({ max: -1, stdTTL: 0, maxStrategy: 'limited', checkperiod: 0, prefix: defaultPrefix }, opts);
_this.storage = new Storage(_this.options.storage, __assign({ memoryScope: ns }, _this.options));
_this.cacheKey = ns;
_this.startCheckperiod();
return _this;
}
Cache.prototype._check = function (key, data) {
var ret = true;
if (data.t !== 0 && data.t < Date.now()) {
ret = false;
this.del(key);
this.emit('expired', key, data.v);
}
return ret;
};
Cache.prototype._wrap = function (value, ttl) {
var now = Date.now();
var currentTtl = typeof ttl === 'number' ? ttl : this.options.stdTTL;
var livetime = currentTtl > 0 ? now + currentTtl : 0;
return {
v: value,
t: livetime,
n: now
};
};
Cache.prototype._isLimited = function (len) {
return this.options.max > -1 && len >= this.options.max;
};
Cache.prototype._getReplaceKey = function (keys, cacheValues) {
var retkey = keys[0];
keys.forEach(function (key) {
if (cacheValues[retkey].n > cacheValues[key].n) {
retkey = key;
}
});
return retkey;
};
Object.defineProperty(Cache.prototype, "cacheValues", {
get: function () {
return this.storage.get(this.cacheKey) || {};
},
enumerable: false,
configurable: true
});
Cache.prototype.setCacheValues = function (values) {
this.storage.set(this.cacheKey, values);
};
Cache.prototype._getData = function (key, cacheValues) {
var data = cacheValues[key];
if (data && this._check(key, data)) {
return data;
}
return;
};
Cache.prototype.get = function (key) {
var data = this._getData(key, this.cacheValues);
return data === null || data === void 0 ? void 0 : data.v;
};
Cache.prototype.mget = function (keys) {
var _this = this;
var ret = {};
if (!Array.isArray(keys)) {
return ret;
}
var cacheValues = this.cacheValues;
keys.forEach(function (key) {
var data = _this._getData(key, cacheValues);
if (data) {
ret[key] = data.v;
}
});
return ret;
};
Cache.prototype.getAll = function () {
var keys = Object.keys(this.cacheValues);
return this.mget(keys);
};
Cache.prototype.set = function (key, value, ttl) {
if (this.options.max === 0) {
return false;
}
var cacheValues = this.cacheValues;
var keys = Object.keys(cacheValues);
if (!cacheValues[key] && this._isLimited(keys.length)) {
var validKeys = this.keys();
if (this._isLimited(validKeys.length)) {
if (this.options.maxStrategy === 'replaced') {
var replaceKey = this._getReplaceKey(validKeys, cacheValues);
this.del(replaceKey);
}
else {
return false;
}
}
}
cacheValues[key] = this._wrap(value, ttl);
this.setCacheValues(cacheValues);
this.emit('set', key, cacheValues[key].v);
return true;
};
Cache.prototype.mset = function (keyValueSet) {
var _this = this;
var ret = true;
keyValueSet.forEach(function (item) {
var itemSetResult = _this.set(item.key, item.value, item.ttl);
if (ret && !itemSetResult) {
ret = false;
}
});
return ret;
};
Cache.prototype.del = function (key) {
var _this = this;
var cacheValues = this.cacheValues;
var count = 0;
var keys = Array.isArray(key) ? key : [key];
keys.forEach(function (key) {
if (cacheValues[key]) {
count++;
var oldData = cacheValues[key];
delete cacheValues[key];
_this.emit('del', key, oldData.v);
}
});
if (count > 0) {
this.setCacheValues(cacheValues);
}
return count;
};
Cache.prototype.clear = function () {
this.storage.del(this.cacheKey);
};
Cache.prototype.keys = function () {
var _this = this;
var cacheValues = this.cacheValues;
var keys = Object.keys(cacheValues);
return keys.filter(function (key) { return _this._check(key, cacheValues[key]); });
};
Cache.prototype.has = function (key) {
return !!this._getData(key, this.cacheValues);
};
Cache.prototype.take = function (key) {
var ret;
var data = this._getData(key, this.cacheValues);
if (data) {
ret = data.v;
this.del(key);
}
return ret;
};
Cache.prototype.ttl = function (key, ttl) {
var data = this._getData(key, this.cacheValues);
if (data) {
return this.set(key, data.v, ttl);
}
return false;
};
Cache.prototype.getTtl = function (key) {
var data = this._getData(key, this.cacheValues);
return data === null || data === void 0 ? void 0 : data.t;
};
Cache.prototype.getLastModified = function (key) {
var data = this._getData(key, this.cacheValues);
return data === null || data === void 0 ? void 0 : data.n;
};
Cache.prototype.startCheckperiod = function () {
var _this = this;
this.keys();
if (this.options.checkperiod > 0) {
clearTimeout(this._checkTimeout);
this._checkTimeout = setTimeout(function () {
_this.startCheckperiod();
}, this.options.checkperiod);
}
};
Cache.prototype.stopCheckperiod = function () {
clearTimeout(this._checkTimeout);
};
return Cache;
}(EmitterPro));
exports.Cache = Cache;
exports.Storage = Storage;
exports.default = Cache;
Object.defineProperty(exports, '__esModule', { value: true });
}));
//# sourceMappingURL=cache2.js.map