====== 第十四部分:故障排除与调试 ======
===== 14.1 常见问题 =====
===== 14.1.1 数据库打开失败 =====
**问题**:indexedDB.open() 报错
**原因**:
* 浏览器隐私模式限制了 IndexedDB
* 存储配额已满
* 浏览器不支持
**解决方案**:
async function safeOpenDB(dbName, version) {
try {
// 检测支持性
if (!window.indexedDB) {
throw new Error('浏览器不支持 IndexedDB');
}
// 检测配额
if (navigator.storage && navigator.storage.estimate) {
const estimate = await navigator.storage.estimate();
if (estimate.usage >= estimate.quota) {
throw new Error('存储空间已满');
}
}
return await openDatabase(dbName, version);
} catch (error) {
console.error('数据库打开失败:', error);
// 降级方案
return new MemoryStorage();
}
}
===== 14.1.2 事务中止 =====
**问题**:TransactionInactiveError 或事务意外中止
**原因**:
* 在异步操作后继续使用事务
* 事务中的操作失败导致整体回滚
**解决方案**:
// 错误示例
async function badExample() {
const transaction = db.transaction(['users'], 'readwrite');
const store = transaction.objectStore('users');
await fetch('/api/check'); // 异步操作!
store.add(data); // TransactionInactiveError!
}
// 正确做法
async function goodExample() {
// 先准备数据
const apiData = await fetch('/api/check').then(r => r.json());
// 再开启事务
const transaction = db.transaction(['users'], 'readwrite');
const store = transaction.objectStore('users');
store.add({ ...data, ...apiData });
}
===== 14.1.3 主键冲突 =====
**问题**:ConstraintError: Key already exists
**解决方案**:
// 方案1:使用 put 替代 add
store.put(data); // 覆盖已有记录
// 方案2:先检查再插入
const existing = await store.get(key);
if (!existing) {
store.add(data);
} else {
console.warn('记录已存在');
}
// 方案3:捕获错误
request.onerror = (event) => {
if (request.error.name === 'ConstraintError') {
event.preventDefault(); // 阻止事务中止
console.warn('主键冲突,跳过');
}
};
===== 14.2 调试技巧 =====
===== 14.2.1 浏览器开发者工具 =====
Chrome/Edge:
* F12 → Application → IndexedDB
* 可查看数据库、对象存储、索引
* 可查看和删除数据
Firefox:
* F12 → Storage → IndexedDB
===== 14.2.2 日志封装 =====
const DEBUG = true;
function log(...args) {
if (DEBUG) {
console.log('[IndexedDB]', ...args);
}
}
function wrapRequest(request, operation) {
return new Promise((resolve, reject) => {
log(`${operation} 开始`);
request.onsuccess = () => {
log(`${operation} 成功`, request.result);
resolve(request.result);
};
request.onerror = () => {
log(`${operation} 失败`, request.error);
reject(request.error);
};
});
}
===== 14.3 错误代码参考 =====
^ 错误名 ^ 说明 ^ 解决方案 ^
| AbortError | 事务被中止 | 检查事务逻辑 |
| ConstraintError | 违反约束 | 检查主键/唯一索引 |
| NotFoundError | 对象存储不存在 | 检查名称拼写 |
| QuotaExceededError | 存储超限 | 清理数据或请求持久化 |
| TransactionInactiveError | 事务已结束 | 避免异步后使用事务 |
| VersionError | 版本错误 | 确保版本号递增 |
===== 14.4 本章小结 =====
本章介绍了 IndexedDB 的故障排除:
* 常见错误及解决方案
* 浏览器开发者工具调试方法
* 日志封装便于排查问题
继续阅读 [[part15-appendix|第十五部分:附录]]。