Last active
December 27, 2021 06:15
-
-
Save wenshin/4f5d5f7e680034149ae9590e9d473ab7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* iOS Webview 中,如果通过打开多个 Webview 来打开页面,那么跨页面的 LocalStorage 和 IndexedDB 都不会及时生效。 | |
* 原因见 https://stackoverflow.com/questions/36332208/two-wkwebviews-share-local-storage-but-only-after-restart | |
* 解决方案: | |
* 1. 参考修改 iOS Webview 调度逻辑 https://stackoverflow.com/questions/36332208/two-wkwebviews-share-local-storage-but-only-after-restart | |
* 2. 使用 Native 提供的 Bridge | |
*/ | |
import { isSupportKVStore, kvGetItem, kvSetItem } from '@/utils/app'; | |
import bridge from '@/utils/bridge'; | |
let dbPromise: Promise<IDBDatabase | null>; | |
const API_CACHE_TABLE = 'hiii-h5-api-cache'; | |
/** | |
* 首次打开 db 大概需要 70ms | |
* @returns | |
*/ | |
function getDB(): Promise<IDBDatabase | null> { | |
if (!dbPromise) { | |
dbPromise = new Promise((resolve) => { | |
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | |
// @ts-ignore | |
const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; | |
if (indexedDB) { | |
const req = indexedDB.open('hiii-h5', 5); | |
req.onsuccess = () => { | |
resolve(req.result); | |
}; | |
req.onerror = (evt) => { | |
console.log('open index db fail', evt); | |
resolve(null); | |
}; | |
req.onupgradeneeded = function onupgradeneeded(evt) { | |
const db = req.result; | |
let objectStore; | |
if (evt.oldVersion < 4) { | |
if (db.objectStoreNames.contains(API_CACHE_TABLE)) { | |
db.deleteObjectStore(API_CACHE_TABLE); | |
} | |
} | |
if (!db.objectStoreNames.contains(API_CACHE_TABLE)) { | |
objectStore = db.createObjectStore(API_CACHE_TABLE, { keyPath: 'key' }); | |
objectStore.createIndex('key', 'key', { unique: true }); | |
} | |
}; | |
} else { | |
resolve(null); | |
} | |
}); | |
} | |
return dbPromise; | |
} | |
function promisifyIDBRequest<T = null>(req: IDBRequest): Promise<T | null> { | |
return new Promise((resolve) => { | |
req.onsuccess = () => { | |
resolve(req.result); | |
}; | |
req.onerror = () => { | |
// 出错,不抛出错误,不阻塞正常流程 | |
console.log('setItem failed'); | |
resolve(null); | |
}; | |
}); | |
} | |
interface StoreItem { | |
key: string, | |
value: any, | |
} | |
export const storageWeb = { | |
async setItem(name: string, value: any) { | |
const db = await getDB(); | |
if (db) { | |
return promisifyIDBRequest( | |
db.transaction([API_CACHE_TABLE], 'readwrite') | |
.objectStore(API_CACHE_TABLE) | |
.put({ key: name, value }) | |
); | |
} else { | |
localStorage.setItem(name, JSON.stringify(value)); | |
} | |
}, | |
async getItem<T>(name: string): Promise<T | null> { | |
const db = await getDB(); | |
if (db) { | |
const item = await promisifyIDBRequest<StoreItem>( | |
db.transaction([API_CACHE_TABLE], 'readwrite') | |
.objectStore(API_CACHE_TABLE) | |
.get(name) | |
); | |
return item && item.value; | |
} else { | |
const str = localStorage.getItem(name); | |
if (str) { | |
return Promise.resolve(JSON.parse(str)); | |
} else { | |
return Promise.resolve(null); | |
} | |
} | |
}, | |
}; | |
export const storage = { | |
async setItem(name: string, value: any) { | |
if (bridge.enabled) { | |
const isSupport = await isSupportKVStore(); | |
if (isSupport) { | |
kvSetItem(name, value); | |
} else { | |
await storageWeb.setItem(name, value); | |
} | |
} else { | |
await storageWeb.setItem(name, value); | |
} | |
}, | |
async getItem<T>(name: string): Promise<T | null> { | |
if (bridge.enabled) { | |
const isSupport = await isSupportKVStore(); | |
if (isSupport) { | |
return kvGetItem<T>(name); | |
} else { | |
return storageWeb.getItem<T>(name); | |
} | |
} else { | |
return storageWeb.getItem<T>(name); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment