怎么使用IndexedDB

发布时间:2021-10-22 09:26:43 作者:iii
来源:亿速云 阅读:475
# 怎么使用IndexedDB

## 一、IndexedDB概述

### 1.1 什么是IndexedDB

IndexedDB是一种在浏览器中存储大量结构化数据的底层API。它是Web Storage API(如localStorage)的更强大替代方案,具有以下关键特性:

- **非关系型数据库**:基于键值对存储,而非传统的关系型表格
- **异步操作**:所有操作都是异步的,不会阻塞UI线程
- **支持事务**:提供ACID事务保证
- **大容量存储**:通常允许存储比localStorage大得多的数据(通常为50MB+)
- **索引支持**:可以创建索引实现高效查询
- **同源策略**:遵循同源策略,不同网站无法访问彼此的数据

### 1.2 适用场景

IndexedDB特别适合以下场景:
- 需要离线工作的Web应用
- 需要存储大量结构化数据的应用
- 需要复杂查询的应用
- 需要存储二进制数据(如图片、文件)的应用

## 二、基本概念

### 2.1 核心组件

1. **数据库(Database)**:顶层的容器,每个源可以创建多个数据库
2. **对象存储(Object Store)**:相当于关系型数据库中的表
3. **索引(Index)**:提供对对象存储中数据的快速查找
4. **事务(Transaction)**:所有操作必须在事务中执行
5. **游标(Cursor)**:用于遍历对象存储或索引中的记录
6. **键(Key)**:每条记录的唯一标识符

### 2.2 数据模型

IndexedDB使用键值对存储数据,其中:
- **键(Key)**:可以是数字、字符串、日期、数组或二进制数据
- **值(Value)**:可以是任何JavaScript对象,包括复杂对象和二进制数据

## 三、基本操作指南

### 3.1 打开/创建数据库

```javascript
const request = indexedDB.open('myDatabase', 1);

request.onerror = (event) => {
  console.error('数据库打开失败:', event.target.error);
};

request.onsuccess = (event) => {
  const db = event.target.result;
  console.log('数据库打开成功');
  // 在这里执行数据库操作
};

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  // 在这里创建或修改对象存储
  if (!db.objectStoreNames.contains('customers')) {
    const store = db.createObjectStore('customers', { keyPath: 'id' });
    // 创建索引
    store.createIndex('name', 'name', { unique: false });
    store.createIndex('email', 'email', { unique: true });
  }
};

3.2 添加数据

function addCustomer(db, customer) {
  const transaction = db.transaction(['customers'], 'readwrite');
  const store = transaction.objectStore('customers');
  
  const request = store.add(customer);
  
  request.onsuccess = () => {
    console.log('客户添加成功');
  };
  
  request.onerror = (event) => {
    console.error('添加客户失败:', event.target.error);
  };
}

3.3 读取数据

3.3.1 通过主键读取

function getCustomer(db, id) {
  const transaction = db.transaction(['customers'], 'readonly');
  const store = transaction.objectStore('customers');
  
  const request = store.get(id);
  
  request.onsuccess = () => {
    if (request.result) {
      console.log('找到客户:', request.result);
    } else {
      console.log('未找到该客户');
    }
  };
  
  request.onerror = (event) => {
    console.error('查询失败:', event.target.error);
  };
}

3.3.2 通过索引查询

function getCustomerByName(db, name) {
  const transaction = db.transaction(['customers'], 'readonly');
  const store = transaction.objectStore('customers');
  const index = store.index('name');
  
  const request = index.get(name);
  
  request.onsuccess = () => {
    if (request.result) {
      console.log('找到客户:', request.result);
    } else {
      console.log('未找到该客户');
    }
  };
}

3.4 更新数据

function updateCustomer(db, customer) {
  const transaction = db.transaction(['customers'], 'readwrite');
  const store = transaction.objectStore('customers');
  
  const request = store.put(customer);
  
  request.onsuccess = () => {
    console.log('客户信息更新成功');
  };
  
  request.onerror = (event) => {
    console.error('更新失败:', event.target.error);
  };
}

3.5 删除数据

function deleteCustomer(db, id) {
  const transaction = db.transaction(['customers'], 'readwrite');
  const store = transaction.objectStore('customers');
  
  const request = store.delete(id);
  
  request.onsuccess = () => {
    console.log('客户删除成功');
  };
  
  request.onerror = (event) => {
    console.error('删除失败:', event.target.error);
  };
}

四、高级操作

4.1 使用游标遍历数据

function getAllCustomers(db) {
  const transaction = db.transaction(['customers'], 'readonly');
  const store = transaction.objectStore('customers');
  
  const customers = [];
  
  store.openCursor().onsuccess = (event) => {
    const cursor = event.target.result;
    if (cursor) {
      customers.push(cursor.value);
      cursor.continue();
    } else {
      console.log('所有客户:', customers);
    }
  };
}

4.2 范围查询

function getCustomersByAgeRange(db, min, max) {
  const transaction = db.transaction(['customers'], 'readonly');
  const store = transaction.objectStore('customers');
  const index = store.index('age');
  
  const range = IDBKeyRange.bound(min, max);
  const customers = [];
  
  index.openCursor(range).onsuccess = (event) => {
    const cursor = event.target.result;
    if (cursor) {
      customers.push(cursor.value);
      cursor.continue();
    } else {
      console.log('年龄范围内的客户:', customers);
    }
  };
}

4.3 批量操作

function batchAddCustomers(db, customers) {
  const transaction = db.transaction(['customers'], 'readwrite');
  const store = transaction.objectStore('customers');
  
  customers.forEach(customer => {
    store.add(customer);
  });
  
  transaction.oncomplete = () => {
    console.log('批量添加完成');
  };
  
  transaction.onerror = (event) => {
    console.error('批量添加失败:', event.target.error);
  };
}

五、最佳实践

5.1 错误处理

  1. 始终检查错误:所有操作都应设置onerror处理程序
  2. 事务错误处理:事务本身也可以有错误处理
  3. 优雅降级:为不支持IndexedDB的浏览器提供备用方案
function handleDBError(error) {
  console.error('数据库错误:', error);
  // 可以在这里实现错误恢复或用户通知
}

// 在所有请求中添加错误处理
request.onerror = (event) => handleDBError(event.target.error);

5.2 性能优化

  1. 批量操作:使用单个事务处理多个操作
  2. 合理使用索引:只为常用查询字段创建索引
  3. 限制数据量:只存储必要的数据
  4. 定期清理:删除不再需要的数据

5.3 版本管理

  1. 版本升级策略:设计良好的版本升级路径
  2. 数据迁移:在onupgradeneeded中处理数据迁移
  3. 兼容性检查:检查当前版本是否需要升级
const DB_VERSION = 2;
const request = indexedDB.open('myDatabase', DB_VERSION);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const oldVersion = event.oldVersion;
  
  if (oldVersion < 1) {
    // 初始版本创建
    db.createObjectStore('customers', { keyPath: 'id' });
  }
  
  if (oldVersion < 2) {
    // 版本2升级
    const transaction = event.target.transaction;
    const store = transaction.objectStore('customers');
    store.createIndex('registrationDate', 'registrationDate');
  }
};

六、常见问题与解决方案

6.1 浏览器兼容性

  1. 检查支持情况
if (!window.indexedDB) {
  console.log('您的浏览器不支持IndexedDB');
  // 提供备用方案
}
  1. 前缀问题:某些浏览器使用带前缀的实现(如webkitIndexedDB)

6.2 事务冲突

  1. 合理设计事务范围:避免长时间运行的事务
  2. 重试机制:对于失败的事务实现重试逻辑

6.3 存储限制

  1. 检查剩余配额
navigator.storage.estimate().then(estimate => {
  console.log(`已使用: ${estimate.usage} bytes`);
  console.log(`剩余: ${estimate.quota - estimate.usage} bytes`);
});
  1. 请求更多存储空间
navigator.storage.persist().then(granted => {
  if (granted) {
    console.log('存储将不会被自动清理');
  }
});

七、实际应用示例

7.1 离线笔记应用

class NotesDB {
  constructor() {
    this.db = null;
    this.init();
  }
  
  init() {
    const request = indexedDB.open('NotesDB', 1);
    
    request.onupgradeneeded = (event) => {
      const db = event.target.result;
      if (!db.objectStoreNames.contains('notes')) {
        const store = db.createObjectStore('notes', {
          keyPath: 'id',
          autoIncrement: true
        });
        store.createIndex('title', 'title', { unique: false });
        store.createIndex('createdAt', 'createdAt', { unique: false });
      }
    };
    
    request.onsuccess = (event) => {
      this.db = event.target.result;
      console.log('数据库初始化完成');
    };
    
    request.onerror = (event) => {
      console.error('数据库初始化失败:', event.target.error);
    };
  }
  
  // 其他方法:addNote, getNote, getAllNotes, updateNote, deleteNote等
}

7.2 文件缓存系统

function cacheFile(db, file) {
  return new Promise((resolve, reject) => {
    const transaction = db.transaction(['files'], 'readwrite');
    const store = transaction.objectStore('files');
    
    const reader = new FileReader();
    reader.onload = (event) => {
      const request = store.put({
        id: file.name,
        name: file.name,
        type: file.type,
        size: file.size,
        lastModified: file.lastModified,
        data: event.target.result
      });
      
      request.onsuccess = () => resolve();
      request.onerror = (event) => reject(event.target.error);
    };
    
    reader.readAsArrayBuffer(file);
  });
}

八、总结

IndexedDB为Web应用提供了强大的客户端存储能力,适合需要存储大量结构化数据的场景。掌握IndexedDB需要理解其核心概念和异步编程模型。通过合理设计数据库结构、正确使用事务和索引,可以构建出性能优异的离线应用。

关键要点回顾:

  1. IndexedDB是异步的、基于事务的键值存储系统
  2. 所有操作必须在事务中执行
  3. 合理使用索引可以提高查询性能
  4. 良好的错误处理是必不可少的
  5. 版本管理需要考虑数据迁移

随着PWA(Progressive Web Apps)的普及,IndexedDB的重要性日益增加,成为现代Web开发中不可或缺的技术之一。 “`

推荐阅读:
  1. indexedDB 数据库
  2. indexedDB存储的案例

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

nosql indexeddb

上一篇:怎么修复Windows 10上的文件夹大小问题

下一篇:Windows 10怎么彻底关闭系统进程

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》