fix:旧浏览器存储方法兼容修改
This commit is contained in:
@@ -3,61 +3,101 @@ import localforage from 'localforage';
|
||||
/** The storage type */
|
||||
export type StorageType = 'local' | 'session';
|
||||
|
||||
// 内存存储的备用实现
|
||||
class MemoryStorage {
|
||||
private static instance: MemoryStorage;
|
||||
private storage = new Map<string, string>();
|
||||
|
||||
static getInstance() {
|
||||
if (!MemoryStorage.instance) {
|
||||
MemoryStorage.instance = new MemoryStorage();
|
||||
}
|
||||
return MemoryStorage.instance;
|
||||
}
|
||||
|
||||
setItem(key: string, value: string) {
|
||||
this.storage.set(key, value);
|
||||
}
|
||||
|
||||
getItem(key: string) {
|
||||
return this.storage.get(key) || null;
|
||||
}
|
||||
|
||||
removeItem(key: string) {
|
||||
this.storage.delete(key);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.storage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 全局备用存储实例
|
||||
const memoryStorage = MemoryStorage.getInstance();
|
||||
|
||||
export function createStorage<T extends object>(type: StorageType) {
|
||||
const stg = type === 'session' ? window.sessionStorage : window.localStorage;
|
||||
// 尝试获取存储实例,如果失败则使用内存存储
|
||||
let stg: Storage | MemoryStorage;
|
||||
|
||||
try {
|
||||
stg = type === 'session' ? window.sessionStorage : window.localStorage;
|
||||
// 测试存储是否可用
|
||||
stg.setItem('__storage_test__', '');
|
||||
stg.removeItem('__storage_test__');
|
||||
} catch (e) {
|
||||
console.warn(`${type} storage is not available, using memory storage`);
|
||||
stg = memoryStorage;
|
||||
}
|
||||
|
||||
const storage = {
|
||||
/**
|
||||
* Set session
|
||||
*
|
||||
* @param key Session key
|
||||
* @param value Session value
|
||||
*/
|
||||
set<K extends keyof T>(key: K, value: T[K]) {
|
||||
const json = JSON.stringify(value);
|
||||
|
||||
stg.setItem(key as string, json);
|
||||
try {
|
||||
const json = JSON.stringify(value);
|
||||
stg.setItem(key as string, json);
|
||||
} catch (e) {
|
||||
console.warn(`Storage set error, falling back to memory storage`);
|
||||
memoryStorage.setItem(key as string, JSON.stringify(value));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Get session
|
||||
*
|
||||
* @param key Session key
|
||||
*/
|
||||
|
||||
get<K extends keyof T>(key: K): T[K] | null {
|
||||
const json = stg.getItem(key as string);
|
||||
if (json) {
|
||||
let storageData: T[K] | null = null;
|
||||
|
||||
try {
|
||||
const json = stg.getItem(key as string);
|
||||
if (!json) return null;
|
||||
return JSON.parse(json);
|
||||
} catch (e) {
|
||||
console.warn(`Storage get error, trying memory storage`);
|
||||
try {
|
||||
storageData = JSON.parse(json);
|
||||
} catch {}
|
||||
|
||||
if (storageData) {
|
||||
return storageData as T[K];
|
||||
const memoryValue = memoryStorage.getItem(key as string);
|
||||
return memoryValue ? JSON.parse(memoryValue) : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
stg.removeItem(key as string);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
remove(key: keyof T) {
|
||||
stg.removeItem(key as string);
|
||||
try {
|
||||
stg.removeItem(key as string);
|
||||
memoryStorage.removeItem(key as string);
|
||||
} catch (e) {
|
||||
console.warn(`Storage remove error`);
|
||||
}
|
||||
},
|
||||
|
||||
clear() {
|
||||
stg.clear();
|
||||
try {
|
||||
stg.clear();
|
||||
memoryStorage.clear();
|
||||
} catch (e) {
|
||||
console.warn(`Storage clear error`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return storage;
|
||||
}
|
||||
|
||||
type LocalForage<T extends object> = Omit<typeof localforage, 'getItem' | 'setItem' | 'removeItem'> & {
|
||||
getItem<K extends keyof T>(key: K, callback?: (err: any, value: T[K] | null) => void): Promise<T[K] | null>;
|
||||
|
||||
setItem<K extends keyof T>(key: K, value: T[K], callback?: (err: any, value: T[K]) => void): Promise<T[K]>;
|
||||
|
||||
removeItem(key: keyof T, callback?: (err: any) => void): Promise<void>;
|
||||
};
|
||||
|
||||
type LocalforageDriver = 'local' | 'indexedDB' | 'webSQL';
|
||||
|
||||
@@ -68,9 +108,97 @@ export function createLocalforage<T extends object>(driver: LocalforageDriver) {
|
||||
webSQL: localforage.WEBSQL
|
||||
};
|
||||
|
||||
localforage.config({
|
||||
driver: driverMap[driver]
|
||||
});
|
||||
// 创建一个内存存储的备用实现
|
||||
const memoryStore = new Map<string, any>();
|
||||
|
||||
return localforage as LocalForage<T>;
|
||||
// 创建备用存储对象
|
||||
const fallbackStorage = {
|
||||
getItem<K extends keyof T>(key: K): Promise<T[K] | null> {
|
||||
return Promise.resolve(memoryStore.get(key as string) || null);
|
||||
},
|
||||
setItem<K extends keyof T>(key: K, value: T[K]): Promise<T[K]> {
|
||||
memoryStore.set(key as string, value);
|
||||
return Promise.resolve(value);
|
||||
},
|
||||
removeItem(key: keyof T): Promise<void> {
|
||||
memoryStore.delete(key as string);
|
||||
return Promise.resolve();
|
||||
},
|
||||
clear(): Promise<void> {
|
||||
memoryStore.clear();
|
||||
return Promise.resolve();
|
||||
},
|
||||
length(): Promise<number> {
|
||||
return Promise.resolve(memoryStore.size);
|
||||
},
|
||||
key(keyIndex: number): Promise<string> {
|
||||
return Promise.resolve(Array.from(memoryStore.keys())[keyIndex]);
|
||||
},
|
||||
keys(): Promise<string[]> {
|
||||
return Promise.resolve(Array.from(memoryStore.keys()));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
// 配置 localforage
|
||||
localforage.config({
|
||||
driver: [
|
||||
driverMap[driver],
|
||||
localforage.LOCALSTORAGE,
|
||||
localforage.INDEXEDDB,
|
||||
localforage.WEBSQL
|
||||
].filter(Boolean),
|
||||
name: 'appStorage',
|
||||
version: 1.0,
|
||||
storeName: 'keyvaluepairs'
|
||||
});
|
||||
|
||||
// 创建包装的存储对象
|
||||
const storage = {
|
||||
getItem<K extends keyof T>(key: K): Promise<T[K] | null> {
|
||||
return localforage.getItem<T[K]>(key as string)
|
||||
.catch(() => fallbackStorage.getItem(key));
|
||||
},
|
||||
setItem<K extends keyof T>(key: K, value: T[K]): Promise<T[K]> {
|
||||
return localforage.setItem<T[K]>(key as string, value)
|
||||
.catch(() => fallbackStorage.setItem(key, value));
|
||||
},
|
||||
removeItem(key: keyof T): Promise<void> {
|
||||
return localforage.removeItem(key as string)
|
||||
.catch(() => fallbackStorage.removeItem(key));
|
||||
},
|
||||
clear(): Promise<void> {
|
||||
return localforage.clear()
|
||||
.catch(() => fallbackStorage.clear());
|
||||
},
|
||||
length(): Promise<number> {
|
||||
return localforage.length()
|
||||
.catch(() => fallbackStorage.length());
|
||||
},
|
||||
key(keyIndex: number): Promise<string> {
|
||||
return localforage.key(keyIndex)
|
||||
.catch(() => fallbackStorage.key(keyIndex));
|
||||
},
|
||||
keys(): Promise<string[]> {
|
||||
return localforage.keys()
|
||||
.catch(() => fallbackStorage.keys());
|
||||
}
|
||||
};
|
||||
|
||||
return storage as LocalForage<T>;
|
||||
} catch (e) {
|
||||
console.warn('Localforage initialization failed, using memory storage', e);
|
||||
return fallbackStorage as LocalForage<T>;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新类型定义
|
||||
interface LocalForage<T extends object> {
|
||||
getItem<K extends keyof T>(key: K): Promise<T[K] | null>;
|
||||
setItem<K extends keyof T>(key: K, value: T[K]): Promise<T[K]>;
|
||||
removeItem(key: keyof T): Promise<void>;
|
||||
clear(): Promise<void>;
|
||||
length(): Promise<number>;
|
||||
key(keyIndex: number): Promise<string>;
|
||||
keys(): Promise<string[]>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user