Initial commit
This commit is contained in:
+168
@@ -0,0 +1,168 @@
|
||||
/** @type {Function} 日志输出 */
|
||||
var log = console.warn;
|
||||
|
||||
/**
|
||||
* 判断值是否为 String 类型
|
||||
* @param {*} str - 待检测值
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
var isString = function (str) { return Object.getTypeString(str) === 'String'; };
|
||||
|
||||
/**
|
||||
* IndexedDB 存储实现(大容量存储优先选择)
|
||||
*
|
||||
* @class IDBStorage
|
||||
* @example
|
||||
* const storage = new IDBStorage('myDb', 'myStore', 1);
|
||||
* await storage.set('key', { data: 123 });
|
||||
* await storage.get('key', null);
|
||||
*/
|
||||
class IDBStorage {
|
||||
/**
|
||||
* 创建 IndexedDB 存储实例
|
||||
* @param {string} [dbName='dbName'] - 数据库名称
|
||||
* @param {string} [storeName='storeName'] - 对象存储名称
|
||||
* @param {number} [version=1] - 数据库版本号
|
||||
*/
|
||||
constructor(dbName, storeName, version) {
|
||||
/** @type {number} 数据库版本号 */
|
||||
this.version = version || 1;
|
||||
/** @type {string} 数据库名称 */
|
||||
this.dbName = dbName || 'dbName';
|
||||
/** @type {string} 对象存储名称 */
|
||||
this.storeName = storeName || 'storeName';
|
||||
|
||||
var request = indexedDB.open(this.dbName, this.version);
|
||||
/** @type {Promise<IDBDatabase>} 数据库连接 Promise */
|
||||
this.requestPromise = new Promise(function (resolve, reject) {
|
||||
request.onupgradeneeded = function (e) {
|
||||
if (e && e.target && !request.result.objectStoreNames.contains(this.storeName)) {
|
||||
request.result.createObjectStore(this.storeName, { keyPath: 'key' })
|
||||
.createIndex('key', 'key', { unique: false });
|
||||
}
|
||||
log('[Index][open]-upgrade');
|
||||
resolve(request.result);
|
||||
}.bind(this);
|
||||
request.onsuccess = function () { log('[IndexDB][open]-success'); resolve(request.result); };
|
||||
request.onerror = function (e) { log('[IndexDB][open]-error', 2); reject(e); };
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取存储值
|
||||
* @template T
|
||||
* @param {string} key - 键名
|
||||
* @param {T} initValue - 默认值(未找到时返回)
|
||||
* @returns {Promise<T>} 存储的值或默认值
|
||||
*/
|
||||
get(key, initValue) {
|
||||
var _this = this;
|
||||
return new Promise(async function (resolve) {
|
||||
var db = await _this.requestPromise;
|
||||
var transaction = db.transaction(_this.storeName, 'readonly');
|
||||
var objectStore = transaction.objectStore(_this.storeName);
|
||||
var req = objectStore.get(key);
|
||||
req.onsuccess = function () { resolve(req.result ? req.result.value : (initValue || null)); };
|
||||
req.onerror = function (e) { log('[indexDB][get]-error', 2, e); resolve(initValue || null); };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置存储值
|
||||
* @template T
|
||||
* @param {string} key - 键名
|
||||
* @param {T} value - 要存储的值
|
||||
* @returns {Promise<T>} 返回写入的值
|
||||
*/
|
||||
set(key, value) {
|
||||
var _this = this;
|
||||
return new Promise(async function (resolve) {
|
||||
var db = await _this.requestPromise;
|
||||
var transaction = db.transaction(_this.storeName, 'readwrite');
|
||||
var objectStore = transaction.objectStore(_this.storeName);
|
||||
var req = objectStore.put({ key: key, value: value });
|
||||
req.onsuccess = function () { resolve(value); };
|
||||
req.onerror = function (e) { log('[indexDB][set]-error', 2, e); resolve(value); };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* localStorage 存储实现(兼容性好,带内存缓存)
|
||||
*
|
||||
* @class ILocalStorage
|
||||
* @example
|
||||
* const storage = new ILocalStorage();
|
||||
* await storage.set('key', { data: 456 });
|
||||
* await storage.get('key', null);
|
||||
*/
|
||||
class ILocalStorage {
|
||||
constructor() {
|
||||
/** @type {Map<string, *>} 内存缓存 */
|
||||
this.cache = new Map();
|
||||
this.load();
|
||||
}
|
||||
|
||||
/** 从 localStorage 全量加载到缓存 */
|
||||
load() {
|
||||
var _this = this;
|
||||
Object.entries(localStorage).forEach(function (entry) {
|
||||
var key = entry[0], value = entry[1];
|
||||
try {
|
||||
_this.cache.set(key, JSON.parse(value));
|
||||
} catch (error) {
|
||||
log('[localStorage][load]-error', 2, error, key, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存获取值
|
||||
* @template T
|
||||
* @param {string} key - 键名
|
||||
* @param {T} initValue - 默认值
|
||||
* @returns {Promise<T>} 缓存的值或默认值
|
||||
*/
|
||||
get(key, initValue) {
|
||||
return new Promise(function (resolve) {
|
||||
resolve(this.cache.get(key) !== undefined ? this.cache.get(key) : initValue);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入 localStorage 并更新缓存
|
||||
* @template T
|
||||
* @param {string} key - 键名
|
||||
* @param {T} value - 要存储的值
|
||||
* @returns {Promise<T>} 返回写入的值
|
||||
*/
|
||||
set(key, value) {
|
||||
return new Promise(function (resolve) {
|
||||
var _value = isString(value) ? value : '';
|
||||
try {
|
||||
_value = JSON.stringify(value);
|
||||
} catch (e) {
|
||||
log('[localStorage][set]-error', 2, e);
|
||||
}
|
||||
localStorage.setItem(key, _value);
|
||||
this.cache.set(key, _value);
|
||||
resolve(value);
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
// 浏览器环境自动选择存储方式
|
||||
if (typeof window !== 'undefined') {
|
||||
/**
|
||||
* 当前环境可用的存储类(IDBStorage 或 ILocalStorage)
|
||||
* @type {Function|null}
|
||||
* @global
|
||||
*/
|
||||
window.IStorage = window.indexedDB ? IDBStorage : (window.localStorage ? ILocalStorage : null);
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = new window.IStorage();
|
||||
}
|
||||
} else if (typeof module !== 'undefined') {
|
||||
module.exports = null;
|
||||
}
|
||||
Reference in New Issue
Block a user