目录

第十四部分:故障排除与调试

14.1 常见问题

14.1.1 数据库打开失败

问题:indexedDB.open() 报错 原因

解决方案

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:

Firefox:

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 的故障排除:

继续阅读 第十五部分:附录