
window.indexedDB.databases() 在多数浏览器(如 Chrome 85+、Firefox 117+)中已支持,但 Safari 和旧版 Edge 完全不支持,直接调用会抛出 TypeError;需先检测方法存在性再执行,否则未捕获的同步错误将中断 Promise 链。
`window.indexeddb.databases()` 在多数浏览器(如 chrome 85+、firefox 117+)中已支持,但 safari 和旧版 edge 完全不支持,直接调用会抛出 `typeerror`;需先检测方法存在性再执行,否则未捕获的同步错误将中断 promise 链。
indexedDB.databases() 是一个实验性但日益普及的 API,用于异步获取当前 Origin 下所有已打开 IndexedDB 数据库的元信息(包括名称、版本等),常用于判断某数据库是否已存在。然而,该方法并非跨浏览器可用:截至 2024 年,Safari 全系(含 iOS/iPadOS)、旧版 Edge(≤18)及部分 Chromium 衍生浏览器仍完全未实现此接口。因此,像 window.indexedDB.databases() 这样的调用在不支持环境中会立即抛出 TypeError——这是一个同步错误,发生在 Promise 创建之前,故 .catch() 无法捕获。
✅ 正确做法是:先进行存在性检测(feature detection),再安全调用。以下是推荐的健壮实现:
/**
* 检查指定名称的 IndexedDB 是否存在(兼容性安全版)
* @param {string} dbName - 数据库名称
* @param {function(boolean): void} [callback] - 可选回调函数,接收布尔值结果
* @returns {Promise<boolean>} 解析为 true(存在)或 false(不存在/不可用)
*/
async function dbExists(dbName) {
// 1. 确保环境支持 indexedDB
if (!('indexedDB' in window)) {
console.warn('IndexedDB not supported in this browser.');
return false;
}
const idb = window.indexedDB;
// 2. 安全检测 databases() 方法是否存在
if (typeof idb.databases === 'function') {
try {
const dbs = await idb.databases();
return dbs.some(db => db.name === dbName);
} catch (err) {
console.warn('Failed to list databases via .databases():', err);
// 回退到传统方式(见下文)
return await fallbackDbCheck(dbName);
}
} else {
// 3. 浏览器不支持 databases() → 使用兼容性回退方案
return await fallbackDbCheck(dbName);
}
}
// 回退方案:尝试打开数据库并监听 onupgradeneeded/onerror
async function fallbackDbCheck(dbName) {
return new Promise(resolve => {
const req = indexedDB.open(dbName, 1);
req.onsuccess = () => {
req.result.close(); // 立即关闭,避免占用连接
resolve(true);
};
req.onupgradeneeded = () => {
// 数据库存在且需升级 → 视为存在
req.result.close();
resolve(true);
};
req.onerror = () => {
// 打开失败(通常因数据库不存在或权限问题)
resolve(false);
};
});
}
// 使用示例
dbExists('myAppDB')
.then(exists => {
console.log('Database exists:', exists); // true / false
if (!exists) {
console.log('Initializing new database...');
// 调用初始化逻辑
}
})
.catch(err => console.error('Unexpected error:', err));</boolean>
⚠️ 重要注意事项:
- ❌ 不要对
indexedDB.databases()做无保护的直接调用(如原代码中的(window.indexedDB.databases()).then(...)),这会导致Uncaught (in promise) TypeError; - ✅ 总是优先使用
typeof idb.databases === 'function'检测能力,而非依赖用户代理或版本号; - ? 回退方案虽可靠,但有轻微副作用:
indexedDB.open()会触发一次轻量级打开流程(不创建数据),在严格隐私模式(如 Firefox 严格跟踪保护)下可能被拦截,此时应结合try/catch+ 用户提示; - ? 若项目已引入 idb 库(推荐),可直接使用其
getDatabases()工具函数(内部已封装兼容逻辑)。
综上,解决该报错的关键不是修正 Promise 链写法,而是前置防御式检测。将能力检测作为第一道关卡,配合优雅降级策略,才能写出真正健壮的 IndexedDB 兼容代码。










