Files
2026-05-27 14:28:02 +08:00

169 lines
5.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** @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;
}