IndexedDB - 错误处理
IndexedDB - 现代错误处理
Section titled “IndexedDB - 现代错误处理”在现代异步 JavaScript 中,处理错误的最佳方式是使用 Promise 和 async/await。原生的 IndexedDB API 是基于事件的,这可能会导致代码冗长。我们可以将 IndexedDB 的请求封装在 Promise 中,以简化代码并使用标准的 try...catch 块进行健壮的错误处理。
IndexedDB 中的错误可能因多种原因而发生:
- 约束违规(例如,尝试添加一个键 (key) 已存在的对象)。
- 超出存储配额。
- 尝试对不再活跃的事务 (transaction) 执行操作。
- 查询不存在的对象仓库 (object store) 或索引 (index)。
未处理的错误通常会中止整个事务,回滚其中所做的任何更改。正确的错误处理使您能够捕获这些问题,通知用户,并防止应用程序崩溃。
将 IndexedDB 请求 Promise 化
Section titled “将 IndexedDB 请求 Promise 化”让我们首先了解如何将一个标准的基于事件的请求转换为 Promise。这种模式是现代 IndexedDB 工作方式的基础。
// 一个将 IDBRequest Promise 化的辅助函数function promisifyRequest(request) { return new Promise((resolve, reject) => { request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); });}示例:处理 ConstraintError
Section titled “示例:处理 ConstraintError”这是一个完整的现代示例,演示了如何捕获 ConstraintError。当尝试添加一个在对象仓库 (object store) 中 keyPath 已存在的对象时,就会发生此错误。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>IndexedDB Modern Error Handling</title></head><body> <h1>Check the console for output.</h1> <script> const DB_NAME = "ErrorHandlingDB"; const DB_VERSION = 1; const STORE_NAME = "products";
async function setupDatabase() { const request = indexedDB.open(DB_NAME, DB_VERSION);
request.onupgradeneeded = (event) => { const db = event.target.result; if (!db.objectStoreNames.contains(STORE_NAME)) { db.createObjectStore(STORE_NAME, { keyPath: "id" }); console.log(`Object store '${STORE_NAME}' created.`); } };
return new Promise((resolve, reject) => { request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); }); }
async function addProduct(db, product) { const transaction = db.transaction(STORE_NAME, "readwrite"); const store = transaction.objectStore(STORE_NAME); const request = store.add(product);
return new Promise((resolve, reject) => { request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); // 该错误将被我们的 try...catch 块捕获 transaction.oncomplete = () => console.log(`Transaction completed for adding product ${product.id}.`); }); }
async function main() { try { const db = await setupDatabase(); console.log("Database opened successfully.");
const product1 = { id: "p1", name: "Laptop", price: 1200 }; await addProduct(db, product1); console.log(`Successfully added product with ID: ${product1.id}`);
// 现在,我们尝试再次添加相同的产品以触发错误 console.log("Attempting to add a duplicate product..."); const product2_duplicate = { id: "p1", name: "Gaming Laptop", price: 1500 }; await addProduct(db, product2_duplicate);
} catch (error) { console.error("An error occurred:", error.name); if (error.name === 'ConstraintError') { console.log("这是一个 ConstraintError。这很可能意味着产品 ID 已经存在。"); } else { console.log("发生了一个意外错误。"); } } }
main(); </script></body></html>常见错误与调试
Section titled “常见错误与调试”- ConstraintError(约束错误): 如上所示,当唯一性约束被违反时(例如,主键重复)会发生此错误。
- TransactionInactiveError(事务不活跃错误): 如果您在事务完成后尝试执行操作,就会发生此错误。请确保所有请求都在创建事务后立即发出。
- NotFoundError(未找到错误): 如果您尝试访问不存在的对象仓库 (object store) 或索引 (index),就会发生此错误。这通常指向版本问题或名称拼写错误。
- DataError(数据错误): 当您尝试保存的数据无效时发生,例如,如果尝试保存一个无法克隆的对象。
- 调试提示: 使用浏览器的开发者工具(应用程序 > 存储 > IndexedDB)来检查数据库、查看其内容并在需要时清除它。