旧版 Safari(iOS 10.3–12.1/macOS 10.1–12.1)IndexedDB 存在四大兼容性问题:全局对象名不一致需按序检测;onupgradeneeded 触发严格且易静默失败;objectStore 创建需预判存在性且索引名须小写下划线;事务易超时中止,游标失效需主动校验 active 状态。
IndexedDB 在旧版 Safari(特别是 iOS 10.3–12.1 和 macOS Safari 10.1–12.1)中存在多个未公开或文档不全的兼容性问题,不是简单加个前缀就能解决,而是需要针对性绕过底层限制。
旧版 Safari 中 window.indexedDB 可能为 undefined,但实际可用的是 window.webkitIndexedDB 或 window.mozIndexedDB(后者是历史残留,不可靠)。不能只检测 indexedDB 是否存在,必须主动检查所有可能的别名。
webkitIndexedDB、mozIndexedDB、indexedDB,取第一个非 undefined 的值open() 方法在 iOS 11.3 之前仍可能抛出 InvalidStateError,需配合错误兜底旧版 Safari 对 onupgradeneeded 的触发极为严格:若数据库已存在且版本号未递增,它不会进入升级流程;更隐蔽的是,即使你显式调用 setVersion()(已废弃 API),也可能被忽略或直接报错。
setVersion(),改用 indexedDB.open(dbName, newVersion) 并确保 newVersion > 当前版本
versionchange 事件再重开高版本onupgradeneeded 不触发 —— 建议加 50ms 防抖或使用 Promise 锁在 Safari 10.1–12.1 中,若在 onupgradeneeded 中重复调用 createObjectStore()(例如缓存逻辑未判断 store 是否已存在),会静默失败,后续 transaction.objectStore() 报 NotFoundError,而非预期的 InvalidStateError。
立即学习“前端免费学习笔记(深入)”;
db.objectStoreNames.contains('storeName') 判断是否存在createIndex()
"updatedAt"),某些 iOS 11.3 以下版本会创建失败 —— 建议统一小写 + 下划线旧版 Safari 的事务生命周期极短:只要 JS 主线程执行超过约 50ms,事务就自动 abort,且不触发 onabort。同时,游标(cursor)在迭代中途若事务关闭,下次 continue() 会抛 TransactionInactiveError,而非返回 done。
setTimeout(..., 0) 让出主线程cursor.continue() 前检查 transaction.active === true,否则重建事务这些问题不是边缘 case,而是旧版 Safari 用户真实遇到的高频崩溃点。绕过方式不复杂,但容易忽略细节导致整个离线功能失效。