WebSQL 被废弃因其未进入 W3C 标准流程,仅是 SQLite 私有实现,而 IndexedDB 成为标准替代方案;二者本质不同:WebSQL 关系型、SQL 驱动,IndexedDB 对象存储、键值+索引驱动,迁移需重构数据访问逻辑。
WebSQL 从未进入 W3C 正式标准流程,它只是基于 SQLite 的私有实现,只有 Chrome、Safari 和旧版 Android 浏览器支持。当 W3C 明确拒绝将其标准化(2010 年起多次讨论后终止),而 IndexedDB 进入标准轨道后,主流浏览器就逐步停止新增功能支持——chrome 133 已移除 WebSQL 的非安全上下文启用能力,Safari 17 在非 HTTPS 页面彻底禁用 window.openDatabase。
WebSQL 是关系型、SQL 驱动;IndexedDB 是对象存储、键值+索引驱动。迁移不是“换函数名”,而是重构数据访问逻辑:
openDatabase → indexedDB.open,但需监听 onupgradeneeded 手动建库建表(即 objectStore)SELECT 或 JOIN,查数据靠 objectStore.get()、objectStore.index('xxx').get() 或游标 openCursor
transaction.objectStore('name') 内进行,离开事务上下文立刻失效IDBKeyRange.bound('a','z'))开发者常把 IndexedDB 当成“带 Promise 的 WebSQL”,结果卡在黑盒错误里:
onupgradeneeded 中创建 objectStore,导致后续 transaction.objectStore('xxx') 报错 NotFoundError: Unknown err
or
get() 或 put(),报 TransactionInactiveError —— 必须把所有操作放在 transaction.oncomplete 之前event.target.result 取值时没检查是否为 undefined(比如 get() 没匹配到),直接解构导致 Cannot read property 'xxx' of undefined
const request = indexedDB.open('mydb', 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains('users')) {
const store = db.createObjectStore('users', { keyPath: 'id' });
store.createIndex('by_email', 'email', { unique: true });
}
};
request.onsuccess = (event) => {
const db = event.target.result;
const tx = db.transaction('users', 'readonly');
const store = tx.objectStore('users');
const emailIndex = store.index('by_email');
const req = emailIndex.get('alice@example.com');
req.onsuccess = () => {
console.log(req.result); // 注意:可能为 undefined
};
};
IndexedDB 原生 API 确实冗长,容易写错。生产项目几乎都封装一层:
idb 库(npm install idb),提供 Promise 化接口和自动事务管理localForage(自动降级到 WebSQL/LocalStorage,但注意 WebSQL 已不可靠)或更现代的 Dexie.js(语法接近 SQL,但底层仍是 IndexedDB)localStorage + JSON.stringify 仍够用;若涉及大量结构化数据或离线同步,IndexedDB 是唯一合规选择真正难的不是 API 本身,而是理解“数据库操作必须绑定生命周期”——事务、版本升级、游标释放,这些概念在 WebSQL 里被 SQL 层掩盖了,换成 IndexedDB 就全摊开在你眼前。