91 lines
2.6 KiB
JavaScript
91 lines
2.6 KiB
JavaScript
function createStorage(storage) {
|
|
const cache = new Map();
|
|
const stringifyCache = new Map();
|
|
const batchWrites = [];
|
|
let flushTimer = null;
|
|
|
|
// 优化的 JSON 序列化
|
|
function fastStringify(obj) {
|
|
const type = typeof obj;
|
|
if (obj === null) return 'null';
|
|
if (type === 'string') return `"${obj}"`;
|
|
if (type === 'number' || type === 'boolean') return String(obj);
|
|
if (type !== 'object') return '{}';
|
|
|
|
const cached = stringifyCache.get(obj);
|
|
if (cached) return cached;
|
|
|
|
try {
|
|
const result = JSON.stringify(obj);
|
|
if (result.length < 1000) {
|
|
stringifyCache.set(obj, result);
|
|
}
|
|
return result;
|
|
} catch {
|
|
return '{}';
|
|
}
|
|
}
|
|
|
|
return {
|
|
set(key, val) {
|
|
if (!key) return;
|
|
|
|
try {
|
|
// 更新缓存
|
|
cache.set(key, val);
|
|
|
|
// 序列化并立即写入
|
|
const serialized = fastStringify(val);
|
|
storage.setItem(key, serialized);
|
|
|
|
// 批量写入作为备份
|
|
batchWrites.push([key, serialized]);
|
|
if (!flushTimer) {
|
|
flushTimer = setTimeout(() => {
|
|
batchWrites.forEach(([k, v]) => {
|
|
try { storage.setItem(k, v); } catch {}
|
|
});
|
|
batchWrites.length = 0;
|
|
flushTimer = null;
|
|
}, 100);
|
|
}
|
|
} catch (e) {
|
|
console.error('Storage error:', e);
|
|
}
|
|
},
|
|
|
|
get(key) {
|
|
if (!key) return null;
|
|
|
|
// 优先读缓存
|
|
const cached = cache.get(key);
|
|
if (cached !== undefined) return cached;
|
|
|
|
try {
|
|
const val = JSON.parse(storage.getItem(key));
|
|
cache.set(key, val);
|
|
return val;
|
|
} catch {
|
|
return null;
|
|
}
|
|
},
|
|
|
|
remove(key) {
|
|
cache.delete(key);
|
|
storage.removeItem(key);
|
|
},
|
|
clear() {
|
|
cache.clear();
|
|
stringifyCache.clear();
|
|
storage.clear();
|
|
batchWrites.length = 0;
|
|
if (flushTimer) {
|
|
clearTimeout(flushTimer);
|
|
flushTimer = null;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
// 导出单例实例
|
|
export const Local = createStorage(window.localStorage);
|
|
export const Session = createStorage(window.sessionStorage); |